这里有新鲜出炉的精品教程, 程序狗速度看过来!
下面小编就为大家带来一篇浅谈 jvm 中的垃圾回收策略小编觉得挺不错的, 现在就分享给大家, 也给大家做个参考一起跟随小编过来看看吧
java 和 C# 中的内存的分配和释放都是由虚拟机自动管理的, 此前我已经介绍了 CLR 中 GC 的对象回收方式, 是基于代的内存回收策略, 其实在 java 中, JVM 的对象回收策略也是基于分代的思想这样做的目的就是为了提高垃圾
回收的性能, 避免对堆中的所有对象进行检查时所带来的程序的响应的延迟, 因为 jvm 执行 GC 时, 会 stop the word, 即终止其它线程的运行, 等回收完毕, 才恢复其它线程的操作基于分代的思想是: jvm 在每一次执行垃圾收集器时, 只是对一小部分内存
对象引用进行检查, 这一小部分对象的生命周期也更短, 从而加快了垃圾收集的性能下面我们将来介绍 java 中的基于代的内存回收算法的基本策略:
一 jvm 堆内存的分代划分
在基于分代的内存回收策略中, 堆空间通常都被划分为 3 个代, 年轻代, 年老代 (或者 tenured 代), 永久代在年轻代中又被划分了三个小的区域, 分别为: Eden(伊甸) 区, S0 区(survivor 0),S1 区(survivor 1), 如下图所示:
其中, 新的对象总被分配到年经代中, 当年轻代空间被填满时, 这时需要执行一次垃圾回收, 即执行 minor GC, 回收不再被引用的对象, 并同时提升幸存的对象其年龄, 年经代中的幸存对象都有年龄标识字段, 一旦其达到一定的阈值, 则仍然幸存的对象将被提升到老年代空间中
老年代的空间用于存放长时间幸存的对象, 即生命周期较长的对象, 一旦年轻代空间的幸存对象达到一定的年龄阈值后, 将被自动提升到年老代, 当年老代空间被对象填满时, 这时执行一次 Major GC 相较于 minor GC, Major GC 的执行次数要比 minor GC 要少很多, 同时, Major Gc 执行的时间较 Minor Gc 要长因为其涉及到更多的对象扫描这种分代的思想, 也是基于在实践中, 对于新分配的对象具有更短的生命周期, 年老的对象具有更长的生命周期所作出的较佳的选择
与此同时, Minor Gc 和 Major Gc 在执行垃圾收集时, 采取的是 stop the world event , 即终止正在运行的线程, 等 GC 执行完毕在恢复所有的线程
对于永久代的内存, 主要是用来存放元数据的相关信息, 类及其方法的信息当一个类不再使用时将会被回收, 当执行 Full GC 时, 将会扫描永久代内存, 对其进行垃圾回收
二基于分代的垃圾回收的处理过程
首先, 初始时, 新对象被分配到 Eden 区域, s0,s1 为空当 Eden 中的空间被填满时, 执行一次 Minor GC 垃圾收集器会将被引用的对象移动 s0 区, 不再被引用的对象将被删除, 与此同时, 对于幸存的对象标识其年龄为 1. GC 后, Eden 和 S1 区为空如下图所示
下一次执行 Minor GC 后, 与先前的执行步骤相同, 唯一的区别时, 这次的被引用的对象, 即幸存下来的对象将会被移动到 S1 区, 与此同时在 s0 区幸存的对象的年龄会增加 1, 变成 2, 如下图所示
当再次, 执行 Minor GC 后, 与先前的步骤相同, 幸存对象会被移到 S0 区, 给幸存对象年龄加 1. 如下图所示
最后执行 Minor GC 时, 发现 S1 中的幸存的对象年龄达到 8(假设阈值 设为 8), 此时该对象将被提升到老年代内存中, 如下图所示
Z
当老年代堆空间被对象填满时, 将会执行一次 Major Gc, 将会清除老年代不再被引用的对象, 与此同时, 对该空间执行压缩如下图所示
来源: http://www.phperz.com/article/18/0318/360214.html