龙空技术网

JVM垃圾回收原理:我们回收的是哪些对象?复制算法的使用

只为奇葩而分享 70

前言:

此时兄弟们对“jvm回收机制原理”可能比较讲究,兄弟们都想要分析一些“jvm回收机制原理”的相关知识。那么小编同时在网络上汇集了一些关于“jvm回收机制原理””的相关资讯,希望同学们能喜欢,你们一起来了解一下吧!

上节我们讲解了JVM中有哪些垃圾回收算法,每个算法各自的优势及它们之间的区别

本节继续讲解JVM垃圾回收原理

那什么情况下JVM内存中的一个对象会被垃圾回收?

如果新生代或老年代里的对象越来越多,都快满了,此时就会触发垃圾回收,把新生代及新生代中没有人引用的对象给回收掉,释放内存空间。

被哪些变量引用的对象是不能回收的?

JVM中使用了一种可达性分析算法来判定哪些对象是可以被回收的,哪些对象是不可以被回收的。这个算法的意思,就是说对每个对象,都分析一下有谁在引用他,然后一层一层往上去判断,看是否有一个GC Roots,有GC Roots引用的对象不能回收没有GC Roots引用的对象可以回收,如果有GC Roots引用,但是如果是软引用或者弱引用的,也有可能被回收掉。在JVM规范中,方法的局部变量就是可以作为GC Roots,静态变量也可以看做是一种GC Roots。

复制算法的优化:Eden区和Survivor区

由于复制算法把新生代分为两块相同区域,新生代用的垃圾回收过后,99%的对象其实都被垃圾回收了,就1%的对象存活了下来,可能就是一些长期存活的对象,或者还没使用完的对象。所以为避免空间浪费,实际上真正的复制算法会做出如下优化,把新生代内存区域划分为三块:

1个Eden区2个Survivor区(分别叫from和to)。

默认比例为8:1其中Eden区占80%内存空间,每一块Survivor区各占10%内存空间,比如说Eden区有800MB内存,每一块Survivor区就100MB内存,如下图:

如果说Eden区域满了,此时必然触发垃圾回收(Minor GC/young GC/YGC)

垃圾回收的时候有一个概念,叫做stop the world,停止你的jvm里的工作线程的运行,然后扫描所有的对象,判断哪些可以回收,哪些不可以回收的。

一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),如果Eden区满了,会进行Minor GC,这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区。对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当它的年龄增加到一定阈值(默认阈值15岁,可配置)时,就会被移动到年老代中

对象进入老年代的条件有很多,后面我们会进行讲解。

因为年轻代中的对象基本都是朝生夕死的(80%以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法不会产生内存碎片。

GC开始时对象只存在Eden区和"From"区,"To"区是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到"To",而在"From"区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定阈值的对象会被移动到年老代中没有达到的对象会被复制到"To"区域。经过这次GC后,Eden区和From区已经被清空。这个时候,"From"和"To"会交换他们的角色,也就是新的"To"就是上次GC前的"From",新的"From"就是上次GC前的"To"。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到"To"区被填满,"To"区被填满之后,会将所有对象移动到年老代中。

对象是达到年龄的就进入老年代中去的吗?是不是只有To区填满后才会进入年老代中去呢?

下节讲解进入老年代规则。

标签: #jvm回收机制原理