目录
JVM堆内存分配
JVM垃圾收集完整过程(带图解)
在介绍垃圾收集过程之前,有必要先对JVM堆内存做一个回顾,因为讲垃圾收集主要针对的是堆内存。
JVM堆内存分配
在JDK1.8之前,JVM堆内存主要分为新生代、老年代和永久代,而在1.8版本之后,永久代被元空间取代,元空间使用直接内存(如图1.1所示)。所以,在JDK1.8之后,在讲堆内存分配的时候,我们主要讲的是新生代和老年代,而新生代进一步可以分为Eden区和两个Survivor区,如图1.2所示。
图1.1
图1.2
针对新生代的垃圾回收称为Minor GC 或者 Young GC,针对老年代的垃圾回收称为Major GC 或者 Old GC,而针对所有的堆内存的垃圾回收称为Full GC。
这里有一点需要注意:通常Major GC和Full GC是等价的,当讲到Major GC的时候,一定要注意区分是仅针对老年代的Old GC 还是 Full GC。(那么,什么时候会触发Full GC 呢?答:历年晋升到老年代的平均对象大小大于老年代剩余空间;或者是如果有永久代,带永久代没有足够空间;或者是System.gc();或者是dump带GC时,都会触发Full GC。)
在新生代中,Eden区域和Survivor区域的内存大小比例为8:2,其中两个survivor(From Survivor和To Survivor,简称S0和S1)的空间大小相等,所以总的新生代内存分配比例为8:1:1。
JVM垃圾收集完整过程(带图解)
1. 对象优先在Eden区域分配
我们都知道,在Eden能够容纳新生对象的时候,对象优先在Eden区域分配内存(先不考虑大对象),如图2.1所示。
图2.1
2. Eden区域满将进行Minor GC
在Eden区域无法容纳新生对象的时候,将会进行一次Minor GC(暂不考虑分配担保问题),如图2.2所示。
图2.2
3. Minor GC使对象进Survivor区域
在进行一次Minor GC时,会将还存活的对象移动到其中一块Survivor区域(S0),并将对象的年龄加1,然后清理Eden区域未被引用的对象,如图2.3所示。
图2.3
4. 再一次Minor GC
经过第一次Minor GC后,Eden区域空了,对象又重新在Eden区域分配内存。当Eden再次满之后,注意 此时将Eden区域被引用的对象和S0中被引用的对象,移动到S1,然后年龄都加1,同时清理Eden和S0区域,如图2.4所示。
图2.4
5. Survivor区域在不断切换
然后再下一次Minor GC时,将重复同样的过程,只是这一次Survivor空间被切换了,如图2.5所示。
图2.5
6. 新生代对象晋升
在重复了几次Minor GC后,如果存活对象的年龄达到一定阈值(此处为8),则会将还存活的对象晋升到老年代,同时对象的年龄加1,如图2.6所示。
图2.6
7. 新生代对象不断晋升
如果对象年龄达到年龄阈值,则不断会有新的对象晋升到老年代,如图2.7所示。
图2.7
8. 老年代Full GC
如果老年代满之后,最终则会进行一次Full GC,如图2.8所示。
图2.8