GC – Garbage Collection – 垃圾回收
本文参考:https://mp.weixin.qq.com/s/bHkgpznnqixDNyDKwdAbOg
-
如何判断对象是否可以清除
JVM中的GC采用根搜索算法,就是选用一些对象作为GC Roots,并组成根对象集合,然后从这些作为GC Roots的对象作为起点,搜索所走过的引用链(Reference Chain)。如果目标对象到GC Roots是连接的,我们称目标对象是可达的,如果目标对象不可达,即表示目标对象是可以被回收的。可以作为GC Root的对象有:
1.JVM栈中引用的对象。
2.方法区中,静态属性引用的对象。
3.方法区中,常量引用的对象。
4.本地方法栈中,JNI(即Native方法)引用的对象。
在JDK1.2之后,引用被分为强引用,软引用,弱引用,虚引用,引用强度依次减弱。 -
GC与分代
由于JVM堆中大部分对象都是短暂临时分配的,如果直接用根搜索算法进行GC,在效率和开销方面并不能满足人们需求。以至于JVM的内存被分为了三个主要部分,新生代,老年代和永久代。
-
新生代
毫无疑问,新生代(Young Generation)中存放的是新生成的对象,而在新生代中,Eden(伊甸园)保存的是最新生成的对象。除此之外还有两个幸存区(Survivor),From survivor 0(S0),To Survivor 1(S1),且都为空。
当第一次Eden区满的时候,会触发GC。此时,在Eden中,被引用的对象会被分配到S0,没有被引用的对象会被清除,此时S1为空。
当再次发生GC时,Eden和S0中被引用的对象会被移动到S1中(采用标记-复制法),未被引用的对象会清除。此时S0为空,S0和S1角色互换,S0为To Survivor,S1为From Survivor。 以后每次GC,重复此步骤,保证S0和S1中有一个为空,用来存储临时对象,进行空间交换。
每次GC后,存活对象的生命周期都会加1,当达到15时,会被分配到老年代的Tenured区中。默认15由参数–XX:MaxTenuringThreshold=15 决定。 -
老年代
老年代用来存储生存时间较长的对象,当老年代中的内存不够时也会触发GC,但是这个GC过程是对新生代和老年代所有对象的回收,也叫Full GC。
老年代管理内存的算法是标记-压缩清除算法。在GC时,把所有标记为不可达的对象清除后,会产生大量的内存碎片,造成一定内存的浪费,为了解决这个问题,在清除后会对内存进行整理和压缩,保证内存连续。 -
永久代
永久代位于方法去,主要存放一些元素据,例如Class、Method等。