Java虚拟机(JVM)是Java平台的核心部分之一,它为Java程序提供了运行环境。
一、历史背景
1. Sun Classic VM
- 发布时间:1996年
- 重要功能:
- Java 1.0的默认JVM。
- 支持基本的字节码执行。
- 简单的垃圾回收机制。
2. HotSpot VM
- 发布时间:1999年
- 重要功能:
- JDK 1.3开始成为默认JVM。
- 引入了即时编译器(JIT Compiler)。
- 提供了多种垃圾收集器。
- 支持线程调度和同步性能的改进。
3. JRockit VM
- 发布时间:2000年初
- 重要功能:
- 由BEA Systems开发,后被Oracle收购。
- 专为高性能企业应用程序设计。
- 强调低延迟和高吞吐量。
4. IBM J9 VM
- 发布时间:2000年初
- 重要功能:
- 由IBM开发,用于IBM的Java平台。
- 高度可定制,支持多种操作系统和硬件平台。
- 提供了广泛的性能监控和调试工具。
5、CMS(Concurrent Mark Sweep)
- 发布时间:2004年(JDK 5.0)
- 重要功能:
- 由Sun Microsystems开发。
- 专注于减少垃圾收集过程中的暂停时间。
- 实现了大部分标记和清除过程与应用程序线程并发执行。
- 在JDK 5.0中作为实验性特性引入,在后续版本中成为稳定特性。
6. Azul VM
- 发布时间:2000年代中期
- 重要功能:
- 由Azul Systems开发。
- 着重于大规模并行处理能力。
- 支持无停顿的垃圾收集(Pauseless GC)。
7. GraalVM
- 发布时间:2014年
- 重要功能:
- 由Oracle Labs开发。
- 支持多种语言(不仅仅是Java)。
- 提供了动态编译能力,可以编译成原生镜像。
8. G1
- 发布时间:2017年(2012年,在JDK 7 Update 4中作为实验性特性)
- 重要功能:
- 低停顿时间:G1的目标是在保证应用运行性能的前提下,尽可能缩短GC停顿时间。
- 内存碎片化管理:通过Region的方式减少内存碎片化的影响。
- 自动管理:G1能够自动调整年轻代和老年代的比例,以达到预期的GC停顿时间目标。
9. ZGC
- 发布时间:2018年(JDK 11中作为实验性特性)
- 重要功能:
- 由Oracle开发。
- 专注于低暂停时间的垃圾收集。
- 在JDK 11中作为实验性特性引入,在JDK 13中成为稳定特性。
10. Shenandoah
- 发布时间:2019年(JDK 12中作为稳定特性)
- 重要功能:
- 专注于低暂停时间的垃圾收集。
- 与ZGC类似,但由不同的团队开发。
- 在JDK 12中成为稳定特性。
11. Epsilon
- 发布时间:2019年(JDK 12中作为实验性特性)
- 重要功能:
- 由Oracle开发。
- 是一个极简的垃圾收集器,几乎不做任何垃圾回收工作。
- 主要用于测试和基准测试。
二、主要垃圾收集器介绍
1、CMS
- CMS 收集器可以在应用程序线程继续运行的同时执行大部分标记过程,从而减少了全局暂停的时间。
- 清除不再使用的对象时,CMS 也可以与应用程序线程并发执行,进一步减少暂停时间。
- CMS 旨在实现低暂停时间的垃圾收集,这对于响应时间敏感的应用程序尤其重要。
- CMS 通常牺牲一定的吞吐量来换取更短的暂停时间,这是通过减少全局暂停次数和持续时间来实现的。
- CMS 特别适合于那些需要高度响应性和低延迟的服务端应用程序。
2、G1
-
1)内存划分:
- G1将整个堆空间划分为多个相同大小的独立区域(Region),每个Region可以充当新生代的Eden区、Survivor区或老年代的一部分。
-
2)并行与并发收集:
- G1可以在多核处理器上并行执行,充分利用硬件资源。
- 它还能够在应用程序运行时进行并发收集,以最小化垃圾收集对应用程序的影响。
-
3)可预测的停顿时间模型:
- G1跟踪各个Region的回收价值,并在后台维护一个优先列表,每次根据允许的收集时间优先回收价值最大的Region,保证在有限的时间内获取尽可能高的收集效率。
- 默认停顿时间为200毫秒,可以通过
-XX:MaxGCPauseMillis
参数设置。 -
4)动态调整年轻代和老年代的比例:
- G1能够自动调整年轻代和老年代的比例,以满足停顿时间目标。
- 新生代的大小可以在5%到60%之间通过
-XX:G1NewSizePercent
和-XX:G1MaxNewSizePercent
参数设置。 -
5)混合回收:
- G1不仅回收老年代的垃圾,也会回收新生代的垃圾,这种混合回收(Mixed GC)策略有助于减少Full GC的次数,提高整体性能。
3、ZGC
-
低暂停时间:
ZGC的主要目标是实现几乎无感的垃圾收集过程,即垃圾收集的暂停时间通常小于10毫秒,甚至在大堆内存环境中也是如此。这一特性对于实时系统和需要低延迟的应用程序非常重要。 -
并发标记与重定位:
- ZGC实现了并发标记和并发重定位,这意味着大多数垃圾收集工作都在应用程序运行时后台完成,减少了停顿时间。
- 标记和重定位阶段都可以与应用程序线程并发执行。
-
可扩展性:
- ZGC支持大规模堆内存环境,可以处理从GB级到TB级的堆内存大小。
- 它能够高效地利用多核处理器的能力来执行并行垃圾收集任务。
-
自动内存管理:
- ZGC能够自动调整堆内存的大小,不需要用户手动干预。
- 它还可以自动调整其内部参数,以适应不同应用程序的需求。
-
无指针压缩:
- ZGC实现了无指针压缩的功能,这意味着在对象移动后,不需要更新堆中的所有引用。
- 这大大减少了对象移动带来的开销,提高了垃圾收集的效率。
三、常见问题及解决方案
-
长时间的GC停顿 (Long GC Pauses)
- 问题描述:应用程序在运行过程中可能会经历较长的垃圾收集停顿时间,导致应用响应变慢或暂时停止响应。
- 解决方案:
- 使用具有较低停顿时间特性的垃圾收集器,如G1或ZGC。
- 调整堆内存大小,适当增加堆内存大小可以减少全堆垃圾收集的发生频率。
- 通过-XX:MaxGCPauseMillis参数设置最大允许的停顿时间,让垃圾收集器尝试在这个时间内完成工作。
-
频繁的Minor GC (Frequent Minor GCs)
- 问题描述:频繁的小型垃圾收集(通常涉及新生代)会导致应用程序性能下降。
- 解决方案:
- 增加新生代的大小,以减少垃圾收集的频率。
- 使用并行或并发的垃圾收集器,例如Parallel或G1。
- 调整-XX:SurvivorRatio参数来改变Survivor区与Eden区的比例,以更好地适应应用程序的工作负载。
-
Full GC (Full Garbage Collection) 频繁发生
- 问题描述:全堆垃圾收集非常耗时,如果频繁发生,会对应用程序造成严重影响。
- 解决方案:
- 减少老年代的使用率,例如通过减少对象的生命周期或者避免长生命周期对象的过早晋升。
- 使用G1或ZGC等垃圾收集器,它们旨在减少Full GC的频率。
- 调整堆内存分配策略,比如使用-XX:+UseAdaptiveSizePolicy让JVM自动管理新生代大小。
-
内存溢出 (OutOfMemoryError)
- 问题描述:当堆内存不足时,JVM会抛出OutOfMemoryError异常。
- 解决方案:
- 增加堆内存大小,例如通过-Xmx和-Xms参数。
- 分析应用程序的内存使用情况,识别内存泄漏并修复。
- 使用工具如VisualVM或JConsole监控内存使用情况,并根据实际情况调整垃圾收集器的配置。
-
内存碎片 (Memory Fragmentation)
- 问题描述:即使总可用内存足够,但由于内存碎片化,也可能无法为大型对象分配足够的连续内存空间。
- 解决方案:
- 使用G1或ZGC等能够处理内存碎片的垃圾收集器,它们支持并发压缩,有助于减少内存碎片。
- 考虑使用CMS收集器的并发模式来减少碎片化,尽管该收集器已被标记为废弃。
通过上述方法,你可以有效地解决常见的垃圾收集问题,从而提高应用程序的性能和稳定性。
四、总结
Java虚拟机(JVM)作为Java平台的核心,自1996年起历经多代发展,如Sun Classic VM、HotSpot VM等,每代都提升了性能与功能。HotSpot VM成为主流,引入JIT编译器和多种垃圾收集器(如CMS、G1、ZGC),优化线程调度与同步。垃圾收集器如CMS、G1、ZGC等,分别通过并发执行、动态调整与低停顿时间等技术,解决了长时间GC停顿、频繁Minor GC、Full GC及内存溢出与碎片等问题,保障了Java应用的性能与稳定性。JVM的持续演进与创新,为Java语言在各类场景下的广泛应用提供了坚实的基础。
标签:JAVA,入门,G1,收集器,应用程序,GC,垃圾,JVM,内存 From: https://blog.csdn.net/qq_40921573/article/details/141613839