JVM垃圾回收算法精讲

判断对象是否可以被回收要区分堆和方法区,堆中对象和方法区中的废弃常量都可以用GC-root可达性分析法来决定,方法区中的无用类要根据三个条件来判断(堆中所有它的实例都没有了,加载该类的classLoader被回收,它的java.lang.class对象没有任何地方引用,包括反射调用)

1,引用计数法:一个对象被引用就+1,失效就-1,为0就可以被回收。实现是每个对象分配一个引用计数器即可。但是有一个问题就是对象循环引用导致没法回收,引起内存泄漏,所以jvm不用此方法。

2,可达性分析:从GC-root对象为起点遍历,按照引用链去找,找到了就说明存活,没有别标记的就是可以回收的对象,要经过俩次标记才能真正判定为回收对象。GC-root对象有四类:(虚拟机栈中的对象,本地方法栈中的对象,方法区中静态属性的引用,方法区中常量引用)

下面就是主流的垃圾回收算法:

1,引用计数

2,标记-清除:分为标记阶段,清除阶段,标记阶段通过可达性分析标记存活对象,没有标记的就是可清除对象,清除阶段将未被标记的内存回收,这样会造成大量磁盘碎片

3,复制算法:将内存分成俩块,一块占满将存活对象复制到另一块,本块将进行清空。优点就是逻辑简单磁盘空间完整这样弥补了标记-清除算法中大量磁盘碎片的问题,但是这个对于磁盘空间就只能使用一半了而且这个适合存活对象少的,效率高。

4,标记-压缩:标记阶段和标记清除阶段的标记是一样的,但不是马上清理,而是将存活对象都移动到一端,然后清理掉端边界以外的内存,这样就弥补了复制算法的内存空间利用不足的问题。

根据分代特点,不同代选用不同的垃圾回收算法即最后jvm选用的分代收集算法:

年轻代(大量无用对象,较少的存活对象)采用复制算法。年轻代又分为三块(Eden:survivor01:survivor02=8:1:1)

年老代(大量存活对象)采用标记-整理算法。

简单描述:先放eden,它满了就回收将存活对象放到survivor01,当survivor满了就将eden+survivor01中的存活对象复制到survivor02,然后清空eden+survivor01,然后交换survivor01和survivor02,如此往复,如果survivor02中不足放存活对象时就将对象放到年老代,如果年老代也满了就出发fullGC(年轻代+年老代一起回收),年轻代大部分触发的是minorGC而且很频繁。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。