JVM垃圾回收机制二

对象的回收

垃圾的回收涉及的几个问题:何时回收,由谁回收,怎样回收。这几个问题我们一一来解决。

1、何时回收----对象的生死判定

对象达到什么条件才能判断这个对象已经无用了。常见的判断对象生死的方法有两种:
(1)引用计数法
给每个对象添加一个引用计数器,只要有地方引用到这个对象,这个对象的计数器就会加1,当引用失效时,计数器就相应的减1。
引用计数法的问题:当两个对象互相引用,并且其他任何地方都没有引用这两个对象,那么根据引用计数法判定就永远无法回收这两个对象。
(2)可达性分析
通过一系列的成为GC Roots的对象作为起点,然后向下搜索,搜索的路径成为引用链,当一个对象到GC Roots没有任何引用链时,那么就说明次对象不可达。
GCRoots对象包括:
方法区:类静态属性引用的对象
方法区:常量引用的对象
虚拟机栈:局部变量表中存储的对象引用引用的对象
本地方法栈:JNI方法引用的对象
关于可达性分析和GC Roots有很多可说的,详细请点-------------------------------

2、怎样回收----垃圾回收算法

通过对象的生死判定算法我们已经知道那些对象已经死了,那我们怎样才能将这些对象回收呢?垃圾回收算法告诉我们这些无用的对象应该怎样回收。垃圾回收算法大体分为三种:复制算法,标记-清除算法,标记整理算法。其中复制算法常用于对新生代的收集,标记清除和标记整理用于对老年代的收集,具体的原因下文会介绍。
(1)复制算法
将可用的内存划分成大小相等的两块,每次只是用其中的一块,当这一块内存使用完了之后,就将还存活的对象复制到另一块内存上,然后把已经使用过的内存空间统一清理掉。

该回收算法的效率虽高,但内存空间的使用效率并不高,因为总是有一般的内存时间使用不上。所以现在商用的JVM虚拟机一般不会将内存空间划分为两个相等的两块,而是划分成一个较大的Eden区和两块较小的Survivor区,Eden和Survivor的比例大小为8:1:1。具体的分代请看https://www.cnblogs.com/ozho/p/10589077.html
(2)标记清除算法
标记清除算法分为标记阶段和清除阶段。
标记阶段:通过可达性分析将需要清除的对象标记
清除阶段:将标记的对象清除。
标记清除算法的问题:效率不高并且会产生大量不连续的内存碎片

(3)标记整理算法
是对标记清除优化的一种算法。在清除阶段之后,会将所有存活的对象移动到内存的一端,然后清理掉剩余可用的内存空间

再谈分代收集
上文已经提到新生代收集由复制算法实现,老年代由标记清除或者标记整理算法实现。新生代收集只能由复制算法实现,老年代只能由标记清除或者标记整理算法实现的原因:
新生代中大多数对象都是“朝生夕死”的,每经过一次Minor GC都会有一大批对象死去,只有少量的对象存活。所以这些少量存活对象复制成本很低,但是在老年代中对象的存活率很高,如果采用Eden区:Suvivor=8:1的比例分配,没有足够的分配空间分配。
永久代的垃圾回收;
永久代的垃圾回收主要为两部分:无用的类和废弃的常量。
关于“由谁回收”的问题下篇继续分析:垃圾回收器
参考:《深入理解JVM虚拟机》

posted on 2019-03-25 18:15  红绿森林  阅读(155)  评论(0编辑  收藏  举报