Java垃圾回收的步骤:
- 标记(Marking)
垃圾回收器标记堆中的对象,哪些依然被引用,哪些不再被引用。
2. 删除(Deleting)
删除不再被引用的对象
3. 压缩(Compacting)
压缩依然被引用的对象,使空闲的堆空间连接在一起,以便加快后续的空间申请
若每一次垃圾回收器在标记过程中,将堆中的对象逐个遍历并对依旧使用的对象进行压缩,会引发巨大时间消耗,显然是不高效的。
通过观察应用程序中对象的生命周期,经验告诉我们:对象在堆中的活动时间往往较短。如下图所示:
因此根据对象在堆中的生存时间,将他们分成3段:Young Generation、Old Generation、 Permanent Generation。
相应的,堆空间可以由如下图所示表示:
所有新生成的对象,存储在Young Generation空间。当Young Generation空间存满时,触发minor garbage collection。不被引用的对象被回收,而依然被引用的对象增加他们的生存时间(age)。当他们的age达到一定阈值时,被转移至Old Generation空间。Old Generation空间在适当的时间触发major garbage collection,进行垃圾回收。Permanent Generation空间存放JVM所需的元数据(metadata),描述应用程序使用的类和方法。Permanent Generation空间在执行full garbage collection时被回收。回收的空间包括不再使用的类等。
Minor garbage collection和major garbage collection都是属于“stop the world”事件。也就是说,在进行垃圾回收时,所有其他的应用线程被阻塞,直到垃圾回收过程结束。
Young Generation空间的垃圾回收过程:
1.首先,所有新生成的对象,被分配到Eden空间。
2.当Eden空间存满时,触发minor garbage collection。
3.被引用的对象被移动至S0空间,然后Eden空间被清空
4.在下一次minor garbage collection时,Eden中被引用的对象转移至S1,S0中被引用的对象转移至S1,并且S0中被引用的对象他们的生存时间增加
5.在下一次minor garbage collection时,相反地,被引用的对象转移至S0。
6.在一次minor garbage collection后,若young Generation中的对象,生存时间超过阈值时,该对象被转移至old generation(下图中的阈值为8)。