JVM垃圾收集

Posted yangyh01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM垃圾收集相关的知识,希望对你有一定的参考价值。

判断对象是否存活的方法:

1、引用计数算法:给一个对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加1,引用失效时,计数器减1,当引用数量为0时,任务对象已经死了

缺点:当对象之间存在相互循环引用时,引用计数算法无法通知GC收集器回收

2、可达性分析算法:判断一个对象到GC ROOTS是否有任何引用链相连,当一个对象到GC ROOTS没有任何引用链相连时,证明此对象是可回收的

在java语言中,可作为GC roots的对象包括下面几种:

虚拟机栈中引用的对象

方法区中类静态属性引用的对象

方法区中常量引用的对象

本地方法栈中JNI(native方法)引用的对象

引用分类:强引用,软引用,弱引用,虚引用

回收方法区:

很多人认为方法区是没有垃圾收集的,在方法区中进行垃圾收集的性价比比较低,在堆中,新生代的进行一次垃圾收集一般可以回收70%到95%,而永久代中的垃圾收集效率远远低于堆,

但是当大量使用反射,动态代理等这类频繁自定义classloader的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出

垃圾收集算法:

标记-清除法:标记完后,统一回收所有被标记的对象,主要不足是:一个是效率问题,标记和清除两个过程的效率都不高,另一个是空间的问题,标记清除后会产生大量不连续的内存碎片,空间碎片太多,可能会导致后续需要分配大内存对象时,无法找到足够连续的内存空间而触发另外一次垃圾收集动作

复制算法:将内存划分为两块大小相等的区域,当其中一块用完时,将还存活的对象复制到另外一块上面,然后再把使用过的内存空间一次清理掉,每次都是对整个半区进行内存回收,内存分配时不用考虑内存碎片等复杂情况

目前虚拟机都采用这种收集算法来回收新生代,将内存划分为一个较大的eden空间和两个较小的survivor空间,每次只是用一个eden区间和一个survivor空间,默认大小比例为8:1,也就是每次新生代中可用内存空间为整个新生代容量的90%,只有10%会浪费,另外没有办法保证每次回收都只有不多余10%的对象存活,当survivor空间不够用时,需要依赖其他内存进行分配担保

标记-整理算法:

复制收集算法在存活率比较高时,会进行较多的复制操作,效率会变低,关键时如果不想浪费50%的空间,就需要有额外的空间进行分配担保,标记-整理算法,后续步骤不是直接对可回收的对象进行清理,而是让所有存活的对象都像一端移动,然后直接清理掉端边界以外的内存

分代收集算法:就是根据对象存活周期的不同将内存划分为几块,一般是把java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最合适的收集算法

 

以上是关于JVM垃圾收集的主要内容,如果未能解决你的问题,请参考以下文章

关于JVM——垃圾收集器

JVM垃圾收集算法

5种JVM垃圾收集器特点和8种JVM内存溢出原因

5种JVM垃圾收集器特点和8种JVM内存溢出原因

JVM垃圾回收-7种垃圾收集器

JVM垃圾回收算法与垃圾收集器