type
status
date
slug
summary
tags
category
icon
password
java 会将内存进行分区,分为新生代和老年代,新生代里面又会分为伊甸园,幸存区 from,幸存区 To,先给伊甸园分配内存,当伊甸园内存满的时候,会进行一次垃圾回收,这是一次小的垃圾回收动作。接着会像之前讲的那样,使用 root标记算法进行标记无用对象,把对象复制进幸存区To 中。

把幸存的对象复制到幸存区之后,把对象的寿命+1,并且交换幸存区from 和幸存区to的指向。然后清除伊甸园里面的无用对象,最后伊甸园又可以放入对象了。这是第一次垃圾回收。

第二次垃圾回收
跟上面的类似,这次幸存区也有对象了,就不仅要扫描伊甸园了,还要扫描幸存区的对象,如果有回收的,那就进行回收,然后对原来的对象寿命+ 1。

每次进行寿命+ 1 有什么用呢,这就体现到老年代区的作用了。当幸存区的对象寿命达到一个阈值的时候,也就是说某个对象经过很多次扫描之后还无法回收,就会把他移动到老年代里面,因为老年代垃圾回收的频率较低,这样可以提高效率,当所有区域都满的话,就会进行一次全扫描,也叫 full GC。
总结
- 对象首先分配在伊甸园区
- 新生代空间不足时,触发 minor gc,也就是一个小回收。伊甸园和 from 存活的对象使用 copy 算法复制到 to 中,存活的对象年龄+ 1,最后交换 from 和 to
- minor gc 会引起 stop the world,会暂停其他用户的线程,等待垃圾回收结束,用户线程才恢复运行。因为垃圾回收的时候可能会改变对象的地址,如果其他用户线程还在运行的话,会造成混乱。
- 当幸存区对象寿命达到阈值的时候,会晋升到老年代。每个对象有4个字节用来记录寿命,最大表示为 1111,也就是 15 次。这是最大,但不同的情况或者虚拟机不同,阈值也不同。
- 当老年代空间不足,会进行一次 full GC,对所有区域进行扫描。