核心内容摘要
穿越失控的七日:当“我”变成“疯子”的旋律
引言垃圾回收Garbage CollectionGC是Java虚拟机JVM的一项重要功能它自动管理内存回收不再使用的对象避免内存泄漏和溢出。
GC不仅在自动化内存管理上起到至关重要的作用而且其算法和回收器的选择直接影响着应用程序的性能。
本文将详细探讨标记清除算法的缺点、垃圾回收的不同阶段、常见的垃圾回收器如CMS和G1的区别及如何选择合适的垃圾回收器等内容。
标记清除算法的缺点标记清除算法Mark-Sweep是最早的垃圾回收算法之一它分为两个阶段标记阶段首先标记所有可达的对象即从根对象出发递归地标记所有可达的对象。
清除阶段清除所有未被标记的对象不可达对象。
尽管标记清除算法较为简单但它有以下缺点效率低标记阶段和清除阶段必须遍历堆中的每个对象尤其是在堆空间较大时效率较低。
空间碎片清除阶段只会将不可达的对象从内存中移除但不会对剩余的内存进行整理。
因此堆内存中可能会出现碎片影响内存的有效使用。
这些缺点在实际应用中会导致GC的效率问题并且可能导致内存碎片化从而降低系统的性能。
垃圾回收算法的哪些阶段会Stop-the-WorldStop-the-WorldSTW是指在垃圾回收过程中所有应用程序线程都会暂停直到垃圾回收完成。
STW暂停时间的长短直接影响应用程序的响应时间。
垃圾回收的以下几个阶段会触发STW标记阶段在标记阶段JVM需要暂停所有应用程序的线程以便准确地标记可达对象。
如果不暂停线程可能会导致标记错误。
转移阶段在某些回收算法如复制算法中转移阶段需要将存活的对象从一个区域移动到另一个区域。
为了保证数据一致性所有应用程序线程会暂停。
重定位阶段重定位阶段涉及调整对象的内存位置通常发生在堆内存的整理过程中同样需要STW暂停应用程序。
STW的暂停时间是垃圾回收的瓶颈之一尤其在低延迟要求的应用中长时间的STW可能影响用户体验。
Minor GC、Major GC、Full GC的区别与触发条件垃圾回收过程可以分为Minor GC、Major GC和Full GCMinor GC主要针对年轻代Young Generation进行回收。
新创建的对象首先进入年轻代当年轻代的内存空间不足时JVM会触发Minor GC。
由于年轻代的对象大多数是短命的Minor GC通常非常频繁且回收效率较高。
Major GC主要针对老年代Old Generation进行回收。
当老年代内存不足时JVM会触发Major GC。
相比Minor GCMajor GC的回收时间较长因为老年代包含了长寿命对象GC过程中需要做更多的标记和清理工作。
Full GCFull GC会回收年轻代和老年代的所有区域包括持久代/元空间。
Full GC是最为耗时的GC类型因为它涉及整个堆内存的回收。
触发Full GC的原因通常是老年代空间不足或者是调用了System.gc()等手动请求垃圾回收的方式。
触发Full GC的场景老年代内存不足时JVM会触发Full GC。
方法区元空间空间不足时JVM会触发Full GC。
手动调用System.gc()方法时。
CMS与G1垃圾回收器的区别CMSConcurrent Mark-Sweep垃圾回收器和G1Garbage First垃圾回收器是两种常见的垃圾回收器它们各自有不同的特点使用范围CMS适用于低延迟要求的应用程序尤其在需要避免长时间停顿的系统中。
适用于老年代的回收。
G1适用于大堆内存的系统尤其是对内存碎片较为敏感的应用。
STW时间CMS通过并行标记和清除阶段来减少STW时间但由于会产生浮动垃圾某些情况下会导致STW暂停较长。
G1通过划分堆内存为多个小区域灵活地回收不同区域的垃圾从而可以更好地控制STW时间。
垃圾碎片CMS可能会产生浮动垃圾即某些对象在回收过程中被标记为可回收但由于并发问题垃圾回收无法及时清除它们导致内存碎片。
G1通过分代式回收和区域化管理减少了垃圾碎片的生成。
垃圾回收过程的不同CMS采用并行标记、并行清除的方式进行回收。
G1通过多个小区域Region的回收和回收优先级策略确保垃圾回收更加精细和可控。
什么情况下使用CMS、什么情况使用G1CMS适用场景需要低延迟的应用程序。
对老年代垃圾回收有需求且要求暂停时间较短。
对垃圾回收的吞吐量有一定要求但不希望出现长时间的停顿。
G1适用场景对大堆内存系统进行优化尤其是内存敏感型应用。
对内存碎片比较敏感希望通过分区和控制回收策略来减少碎片。
需要平衡性能和停顿时间的系统。
G1回收器的特点G1垃圾回收器Garbage First是为大内存应用设计的它通过将堆内存划分为多个小区域Region并动态选择回收优先级来有效地进行垃圾回收。
其主要特点包括高效的停顿时间控制通过优先回收垃圾最多的区域G1能够有效控制停顿时间。
分代式回收G1结合了年轻代和老年代的回收机制并且能够根据不同的回收需求来灵活调整。
适应大堆内存G1特别适用于大堆内存的系统尤其是对内存碎片敏感的应用。
GC只会对堆进行回收吗还会对方法区进行回收GC不仅会回收堆内存还会对方法区JDK 8之前的持久代或元空间JDK 8及以后进行回收。
具体来说堆内存GC会清理年轻代和老年代的垃圾对象释放内存空间。
方法区元空间随着类的加载和卸载JVM会进行方法区的回收。
在JDK 8之前方法区是通过持久代实现的GC会回收不再使用的类元数据在JDK 8及以后方法区被元空间取代元空间的回收由GC负责。