架构师训练营第九周
请简述 JVM 垃圾回收原理。
Java回收方式:minor gc、major gc、full gc
Minor gc从年轻代空间(包括 Eden 和 Survivor 区域)回收内存,Minor gc 触发条件:
(1)当 JVM 无法为一个新的对象分配空间时会触发 Minor GC,比如当 Eden 区满了。
major gc是清理永久代。
full gc 是清理年轻代和永久代。
Full GC触发条件:
(1)调用System.gc时,系统建议执行Full GC,但是不必然执行
(2)老年代空间不足
(3)方法区空间不足
(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存
(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小。
垃圾回收算法:
(1)标记清除算法:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。不足之处:一个是效率问题,标记和清除两个过程的效率都不高;另一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
(2)复制算法:一种称为“复制”(Copying)的收集算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。
不足之处:只是这种算法的代价是将内存缩小为了原来的一半,未免太高了一点。
(3)标记整理算法:标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
(4)分代收集算法:在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。 而老年代中因为对象存活率高、 没有额外空间对它进行分配担保,就必须使用“标记—清理”或者“标记—整理”算法来进行回收。
垃圾回收的垃圾收集器有:
1. Serial收集器
这个收集器是一个单线程的收集器,但它的“单线程”的意义并不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。
2.ParNew
Serial多线程版本。
3. Parallel Scavenge收集器
Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量(Throughput)
4. Serial Old收集器
它同样是一个单线程收集器,使用“标记-整理”算法
5. Parallel Old收集器
是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
6.CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集
器。
主要包含下面4个步骤:初始标记(CMS initial mark)、并发标记(CMS concurrent mark)、重新标记(CMS remark)、并发清除(CMS concurrent sweep)。初始标记和重新标记需要stop the word。
7.G1收集器
并行与并发:G1能充分利用多CPU、 多核环境下的硬件优势,使用多个CPU(CPU或者
CPU核心)来缩短Stop-The-World停顿的时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让Java程序继续执行。
分代收集:与其他收集器一样,分代概念在G1中依然得以保留。
空间整合:与CMS的“标记—清理”算法不同,G1从整体来看是基于“标记—整理”算法实现的收集器,从局部(两个Region之间)上来看是基于“复制”算法实现的,但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。 这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。
可预测的停顿:这是G1相对于CMS的另一大优势,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。
评论