后续将持续更新完善,如果有想要补充的知识点,请留言
如果有误,欢迎留言讨论纠正
jvm 含义解释
1、Java虚拟机(Java Virtual Machine)它是Java运行时环境的一部分,用于执行Java程序。JVM负责将Java源代码编译成字节码并执行,提供了内存管理、垃圾回收、安全性、线程管理等功能。可通过不同系统的jvm实现跨平台运行
2、当编译.java文件时,Java 编译器会生成与.java文件中的类名相同的.class文件(包含字节码) 。运行此.class文件时,它会经历多个步骤。这些步骤共同描述了整个 JVM。
一、主要组成部分
1. 类加载器子系统
主要负责三项活动
1、加载中
1、类加载器读取“.class ”文件,生成相应的二进制数据并
保存在方法区
中。
2、对于每一个“ .class”文件,JVM在方法区中存储以下信息:已加载类及其直接父类的完全限定名称
、
“ .class”文件是否与 Class 或 Interface 或 Enum 相关
,修饰符
、变量
和方法信息
等。
3、加载“ .class”文件后,JVM 会创建一个 Class 类型的对象来表示堆内存
中的此文件。请注意,此对象是java.lang包中预定义的 Class 类型。程序员可以使用这些 Class 对象来获取类级信息(如类的名称、父名称、方法和变量信息)
等。
4、要获取此对象引用
,我们可以使用Object类的getClass()方法。2、链接
执行验证、准备和(可选)解决。
1、验证:它确保.class文件的正确性,即检查此文件是否格式正确且是否由有效的编译器生成。如果验证失败,我们会得到运行时异常java.lang.VerifyError。此活动由组件 ByteCodeVerifier 完成。完成此活动后,类文件即可进行编译。
2、准备:JVM 为类静态变量分配内存并将内存初始化为默认值。
3、解析:使用直接引用来替换类型的符号引用的过程。通过搜索方法区来定位引用的实体。3、初始化
在此阶段,所有静态变量均被赋予在代码和静态块(如果有)中定义的值。
此过程在类中从上到下执行,在类层次结构中从父类到子类执行。
一般来说,有三个类加载器:
>> 引导类加载器 <<:每个 JVM 实现都必须有一个引导类加载器,能够加载受信任的类。它加载“JAVA_HOME/lib”目录中的核心 Java API 类。此路径通常称为引导路径。它以 C、C++ 等本机语言实现。
>> 扩展类加载器 <<:它是引导类加载器的子类。它加载扩展目录“ JAVA_HOME/jre/lib/ext” (扩展路径)或 java.ext.dirs 系统属性指定的任何其他目录中的类。它在 Java 中由sun.misc.Launcher$ ExtClassLoader类实现。
>> 系统/应用程序类加载器 <<:它是扩展类加载器的子类。它负责从应用程序类路径加载类。它在内部使用映射到 java.class.path 的环境变量。它也由sun.misc.Launcher$AppClassLoader类在 Java 中实现。
注意: JVM 遵循委托层次原则来加载类。系统类加载器将加载请求委托给扩展类加载器,扩展类加载器将请求委托给引导类加载器。如果在引导路径中找到类,则加载该类,否则请求再次转移到扩展类加载器,然后转移到系统类加载器。最后,如果系统类加载器无法加载类,则我们会得到运行时异常java.lang.ClassNotFoundException。
2. 类加载器
类加载器主要有三种类型:
Bootstrap Class Loader
:从目录中加载核心 Java API 类JAVA_HOME/lib。它以本机代码实现,不是 Java 对象。
扩展类加载器
:从JAVA_HOME/jre/lib/ext目录或系统属性指定的任何目录中加载类java.ext.dirs。它用 Java 实现。
系统/应用程序类加载器
:从java.class.path环境变量指定的应用程序类路径加载类。它也是用 Java 实现的。
3. JVM 内存 区域
方法区
:方法区中存储了所有类级别的信息,包括类名、直接父类名、方法和变量信息等,包括静态变量。每个 JVM 只有一个方法区,并且是共享资源
。
堆区域
`:所有对象的信息都存储在堆区域中。每个 JVM 也有一个堆区域。它也是共享资源
。
堆栈区域
:对于每个线程,JVM 都会创建一个运行时堆栈并存储在此处。此堆栈的每个块称为激活记录/堆栈框架,用于存储方法调用。该方法的所有局部变量都存储在其相应的框架中
。线程终止后,其运行时堆栈将被 JVM 销毁。它不是共享资源
。
PC寄存器
:存放线程当前执行指令的地址,显然每个线程都有独立的PC寄存器
。
本机方法堆栈
:对于每个线程,都会创建一个单独的本机堆栈
。它存储本机方法信息。
4.执行引擎
执行引擎执行“ .class”(字节码)。它逐行读取字节码,使用各个内存区域中存在的数据和信息并执行指令
分为以下三个部分:
解释器
:将字节码逐行解释然后执行。这里的缺点是当一个方法被多次调用时,每次都需要解释。
即时编译器 (JIT)
:用于提高解释器的效率。它编译整个字节码并将其更改为本机代码,因此每当解释器看到重复的方法调用时,JIT 都会为该部分提供直接本机代码,因此不需要重新解释,从而提高了效率。
垃圾收集器
:它会销毁未引用的对象。
5.Java 本机接口(JNI)
一个与本机方法库交互的接口,提供执行所需的本机库(C、C++)。它使 JVM 能够调用 C/C++ 库,并被可能特定于硬件的 C/C++ 库调用。
6. 本机方法库
这些是执行本机方法所需的本机库的集合。它们包括用 C 和 C++ 等语言编写的库。
二、垃圾回收器(Garbage Collector )
一种内存管理工具
分代
1、在初始化时,虚拟地保留最大地址空间,但除非需要,否则不会分配给物理内存。为对象内存保留的完整地址空间可分为年轻代和老年代。
2、年轻代由伊甸园和两个幸存者空间组成。大多数对象最初都分配在伊甸园中。一个幸存者空间在任何时候都是空的
,并作为伊甸园中任何存活对象的目的地;另一个幸存者空间是下一次复制收集期间的目的地。对象以这种方式在幸存者空间之间复制,直到它们足够老到可以成为老生代(复制到老生代)。
3、选择特定代的大小是这些考虑因素之间的权衡。例如,非常大的年轻代可能会最大化吞吐量,但这样做会以占用空间、及时性和暂停时间为代价
。使用较小的年轻代可以最大限度地减少年轻代的暂停,但会牺牲吞吐量
。
4、一个代的大小不会影响另一个代的收集频率和暂停时间。
5、没有一种正确的方法来选择代的大小。最佳选择取决于应用程序使用内存的方式以及用户要求
。
垃圾收集算法
1. 标记-清除
通过根可达性分析,标记出需要回收的对象(不可达的对象),对有标记的对象进行回收。缺点:需要回收的对象过多时,会存在大量的标记,并且回收后存在垃圾碎片。
2. 标记-复制
通过可达性分析,找出非垃圾对象(可达的对象),复制到另一块内存区域,清空前一个内存区域。优点:内存连续。缺点:内存利用率只有50%,如果存活对象过多,会增加复制耗时,且只能回收少量的内存空间。
3. 标记-整理
通过可达性分析,标记存活对象,整理存活对象向内存空间的一侧移动,清空标记指针另一侧内存地址。优点:内存连续,有新对象加入时,根据对象大小,移动指针即可。缺点:内存对象过多时,需要移动大量的存活对象,才能回收垃圾对象,释放内存地址。
注意:回收算法并非固定,都有各自的优缺点,根据不同的场景采用合适回收的算法,才能提高性能。
垃圾收集器
串行收集器
:使用单个线程执行所有垃圾收集工作,这使得它相对高效,因为线程之间没有通信开销。它最适合单处理器计算机,因为它无法利用多处理器硬件,尽管对于具有小数据集(最多约 100 MB)的应用程序,它在多处理器上很有用。在某些硬件和操作系统配置中,串行收集器是默认选择的,也可以使用选项明确启用-XX:+UseSerialGC。
并行收集器
:(也称为吞吐量收集器)并行执行次要收集,这可以显著减少垃圾收集开销。它适用于在多处理器或多线程硬件上运行的具有中型到大型数据集的应用程序。在某些硬件和操作系统配置上,并行收集器是默认选择的,也可以使用选项明确启用-XX:+UseParallelGC。
并行收集器优先级:最大暂停时间目标 > 吞吐量目标 > 最小空间目标
并行压缩
是一项功能,可使并行收集器并行执行主要收集。如果没有并行压缩,主要收集将使用单个线程执行,这会严重限制可扩展性。如果-XX:+UseParallelGC指定了 选项,则默认启用并行压缩。关闭它的选项是-XX:-UseParallelOldGC。大部分
并发收集器
会并发执行大部分工作(例如:在应用程序仍在运行时),以缩短垃圾收集暂停时间。它专为具有中型到大型数据集的应用程序而设计
,在这些应用程序中,响应时间比总体吞吐量更重要,因为用于最小化暂停的技术可能会降低应用程序性能。Java HotSpot VM 提供了两种大部分并发收集器之间的选择;使用该选项-XX:+UseConcMarkSweepGC启用 CMS 收集器或-XX:+UseG1GC启用 G1 收集器。
如何选择收集器
:除非您的应用程序对暂停时间有相当严格的要求,否则请先运行您的应用程序并允许 VM 选择收集器。如有必要,请调整堆大小以提高性能。如果性能仍未达到您的目标,请使用以下指南作为选择收集器的起点。
1、如果应用程序的数据集较小(最多约 100 MB),则使用选项选择串行收集器-XX:+UseSerialGC。
2、如果应用程序将在单个处理器上运行并且没有暂停时间要求,则让 VM 选择收集器,或者使用选项选择串行收集器-XX:+UseSerialGC。
3、如果 (a) 应用程序峰值性能是第一优先级,且 (b) 没有暂停时间要求或者可以接受 1 秒或更长时间的暂停,则让 VM 选择收集器,或者选择并行收集器-XX:+UseParallelGC。
4、如果响应时间比总体吞吐量更重要,并且垃圾收集暂停必须保持在 1 秒以下,则选择带有-XX:+UseConcMarkSweepGC 或 的并发收集器-XX:+UseG1GC。
这些准则仅提供了选择收集器的起点,因为性能取决于堆的大小、应用程序维护的实时数据量以及可用处理器的数量和速度
。暂停时间对这些因素特别敏感,因此前面提到的 1 秒阈值只是近似值:并行收集器在许多数据大小和硬件组合上都会遇到超过 1 秒的暂停时间;相反,并发收集器在某些组合上可能无法将暂停时间保持在 1 秒以下。
如果推荐的收集器未达到预期性能,请首先尝试调整堆和代大小以满足预期目标。 如果性能仍然不足,请尝试其他收集器:使用并发收集器减少暂停时间,使用并行收集器增加多处理器硬件上的整体吞吐量。
1. Serial 收集器
单线程
的垃圾收集器,使用标记-复制
算法,进行垃圾回收,会暂停用户线程。Client模式下,默认新生代
收集器;
2. ParNew 收集器
Serial 收集器的
多线程
版本,Server模式下,默认新生代
收集器,除了Serial收集器,只有它能配合CMS收集器工作。
3. Parallel Scavenge 收集器(吞吐量优先)
与ParNew收集器相似,
新生代
收集器,多线程
版本,但不会停止用户线程,与用户线程并行。
4. Serial Old收集器
Serial Old是Serial收集器的
老年代
版本,,采用标记-整理
算法,同样是一个单线程收集器
。给Client模式下的虚拟机使用。
5. Parallel Old 收集器(吞吐量优先)
Parallel Scavenge 收集器的
老年代
版本,也是多线程
,采用标记-整理
算法。
UseParallelGC 即 Parallel Scavenge + Parallel Old,即JDK1.8默认垃圾回收器为ParallelGC:并行垃圾收集器
6. CMS(ConcMarkSweepGC – 并发标记清除)
CMS 是分代收集器,基于
标记-清除算法
,小收集和大收集都会发生,是一种增量更新收集器。
具有相对较大一组长期生存数据(较大的老年代)
并在具有两个或更多处理器
的机器上运行的应用程序往往会从使用此收集器中受益。但是,对于任何具有较低暂停时间要求
的应用程序,都应考虑使用此收集器。
``CMS 收集器通过命令行选项启用-XX:+UseConcMarkSweepGC。`
- 初始标记(初始暂停)
从
根
(例如:来自应用程序线程堆栈和寄存器的对象引用、静态对象等)和堆中的其他位置
(例如年轻代)直接访问的对象标记为活动对象,此阶段会STW(暂停)
- 并发标记跟踪
在此并发跟踪阶段,一个或多个并发垃圾收集器线程可能正在使用应用程序原本可用的处理器资源。因此,即使应用程序线程
未暂停
,计算受限的应用程序在此阶段和其他并发阶段可能会看到应用程序吞吐量相应下降。
- 重新标记(标记暂停)
并发跟踪阶段结束时,并
查找
由于 CMS 收集器完成跟踪某个对象后应用程序线程对该对象的引用进行更新而导致并发跟踪遗漏的对象
,此时也会STW(暂停)
- 并发清除
收集被标识为不可到达的对象(垃圾对象)
收集周期完成后,CMS 收集器将等待,几乎不消耗任何计算资源,直到下一个主要收集周期开始。
7. G1( Garbage First GC )
G1 一种增量式垃圾收集器,是一个压缩收集器,具有统一的暂停时间,但应用程序线程的开销也更大,适用于具有大内存的多处理器计算机。它试图以高概率满足垃圾收集 (GC) 暂停时间目标,同时实现高吞吐量。整个堆操作(例如全局标记)与应用程序线程同时执行。这可以防止与堆或实时数据大小成比例的中断。堆被划分为一组大小相等的堆区域,每个区域都是一段连续的虚拟内存。
- 初始标记阶段
G1 GC 在此阶段标记根。此阶段
需要 (STW)
年轻垃圾收集上。
- 根区域扫描阶段
G1 GC 扫描初始标记的幸存区域以查找对老一代的引用,并标记引用的对象。此阶段与应用程序同时运行,并且必须在下一次 STW 年轻垃圾回收开始之前完成。
- 并发标记阶段
G1 GC 在整个堆中查找可访问(活动)对象。此阶段与应用程序同时发生,并可能被 STW 年轻垃圾收集中断。
- 最终标记阶段
此阶段是
STW 收集
,有助于完成标记周期。G1 GC 清空 SATB 缓冲区,跟踪未访问的活动对象,并执行引用处理。
- 清理阶段
在此最后阶段,G1 GC 执行,
部分STW
,即核算和 RSet 清理。在核算期间,G1 GC 会识别完全空闲的区域和混合垃圾收集候选区域,将存活对象复制到新区域中。清理阶段是部分并发的,它会重置并将空区域返回到空闲列表。
从逻辑上讲,G1 是分代的。一组空区域被指定为逻辑年轻代。在图中,年轻代为浅蓝色
,分配在该逻辑年轻代之外,当年轻代已满时,该组区域将被垃圾收集(年轻收集)。在某些情况下,年轻区域集之外的区域(深蓝色的旧区域)可以同时被垃圾收集。这被称为混合收集。在图中,正在收集的区域用红色框标记
。该图说明了混合收集,因为正在收集年轻区域和旧区域。垃圾收集是一种压缩收集,它将活动对象复制到选定的最初为空的区域。根据幸存对象的年龄,可以将对象复制到幸存区域(标记为“S”)或旧区域(未具体显示)。标记为“H”的区域包含大于半个区域并被特殊处理的巨型对象;
详细介绍
默认配置参数列表
其他信息
启动并发收集周期
:使用串行收集器时,只要老年代已满,就会发生主要收集,并且在收集完成时所有应用程序线程都会停止。相比之下,并发收集的启动时间必须确保收集可以在老年代已满之前完成
;否则,由于并发模式失败,应用程序会观察到更长的暂停。以下是可以启动并发收集的方法:
1、根据最近的历史记录,CMS 收集器会估计在老年代耗尽之前剩余的时间以及并发收集周期所需的时间,使用这些动态估计值,可以启动并发收集周期,以在老年代耗尽之前完成收集周期。这些估计值是出于安全考虑而填充的,因为并发模式失败的代价可能非常高昂。
2、如果老年代的占用率超过初始占用率(老年代的百分比),也会启动并发收集。此初始占用率阈值的默认值约为 92%,但该值会随着版本的不同而变化。可以使用命令行选项手动调整此值-XX:CMSInitiatingOccupancyFraction=<N>
,其中是老年代大小的整数百分比(0 到 100)。
暂停时机
:年轻代收集和老年代收集的暂停是独立发生
的。它们不重叠,但可能会快速连续发生,因此一个收集的暂停紧接着另一个收集的暂停,看起来就像一个较长的暂停。为了避免这种较长的暂停,CMS 收集器会尝试将标记暂停安排在上一个和下一个年轻代暂停的中间位置
。目前,初始标记暂停不会进行此安排,因为初始标记暂停通常比标记暂停短得多。
垃圾收集器关系图
关键字解释
STW
:(Stop To World)暂停
指由于正在进行垃圾收集而导致应用程序无响应的时间。
并行收集器的目标优先级
目标按以下顺序实现:最大暂停时间目标 > 吞吐量目标 > 最小空间目标
首先要满足最大暂停时间目标。只有满足了最大暂停时间目标,才会考虑吞吐量目标。同样,只有满足了前两个目标,才会考虑占用空间目标。
垃圾回收日志
[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->83769K(776768K), 1.8479984 secs]
输出显示两次次要回收,随后是一次Full GC。
1、箭头前后的数字(例如,325407K->83000K第一行)分别表示垃圾回收前后活动对象的总大小。在次要回收之后,大小包括一些垃圾(不再活动)但无法回收的对象。这些对象要么包含在老年代中,要么从老年代中引用。
2、括号中的下一个数字(例如,(776768K)同样来自第一行)是堆的已提交大小:无需向操作系统请求更多内存即可用于 Java 对象的空间量。请注意,此数字仅包括一个幸存者空间。除了垃圾回收期间,在任何给定时间都只会使用一个幸存者空间来存储对象。
3、该行的最后一项(0.2300771 secs)表示执行收集所需的时间,在本例中约为四分之一秒。
Using Parallel
[2024-11-01T20:23:48.404+0800][3.461s] GC(6) Pause Full (Metadata GC Threshold)
[2024-11-01T20:23:48.404][3.461s] GC(6) Marking Phase
[2024-11-01T20:23:48.429][3.486s] GC(6) Marking Phase 24.869ms
[2024-11-01T20:23:48.429][3.486s] GC(6) Summary Phase
[2024-11-01T20:23:48.429][3.486s] GC(6) Summary Phase 0.011ms
[2024-11-01T20:23:48.429][3.486s] GC(6) Adjust Roots
[2024-11-01T20:23:48.433][3.490s] GC(6) Adjust Roots 4.043ms
[2024-11-01T20:23:48.433][3.490s] GC(6) Compaction Phase
[2024-11-01T20:23:48.456][3.512s] GC(6) Compaction Phase 22.105ms
[2024-11-01T20:23:48.456][3.512s] GC(6) Post Compact
[2024-11-01T20:23:48.456][3.513s] GC(6) Post Compact 0.553ms
[2024-11-01T20:23:48.456][3.513s] GC(6) PSYoungGen: 5911K(139264K)->0K(139264K) Eden: 0K(131072K)->0K(131072K) From: 5911K(8192K)->0K(8192K)
[2024-11-01T20:23:48.456][3.513s] GC(6) ParOldGen: 7619K(86016K)->12972K(86016K)
[2024-11-01T20:23:48.456][3.513s] GC(6) Metaspace: 21093K(21504K)->21093K(21504K) NonClass: 18547K(18816K)->18547K(18816K) Class: 2546K(2688K)->2546K(2688K)
[2024-11-01T20:23:48.456][3.513s] GC(6) Pause Full (Metadata GC Threshold) 13M->12M(220M) 51.695ms
[2024-11-01T20:23:48.456][3.513s] GC(6) User=0.09s Sys=0.00s Real=0.05s开始的 GC 信息
[2024-11-01T20:23:48.404][3.461s] GC(6) Pause Full (Metadata GC Threshold)
时间戳: 2024-11-01T20:23:48.404+0800 表示发生 GC 的时间。
GC(6): 第 6 次 GC,标识该回收事件。
Pause Full: 这是一次全堆(Full GC)回收,涉及年轻代和老年代。
(Metadata GC Threshold): 表明此次 GC 是因为类元数据的使用量超过了设置的阈值。
GC 阶段信息
[2024-11-01T20:23:48.404][3.461s] GC(6) Marking Phase
Marking Phase:开始标记阶段,标记所有存活的对象
。
[2024-11-01T20:23:48.429+0800][3.486s] GC(6) Marking Phase 24.869ms
时间:标记阶段的耗时
为 24.869 毫秒。
[2024-11-01T20:23:48.429][3.486s] GC(6) Summary Phase
Summary Phase:开始汇总阶段,整理标记结果并准备进行下一步的根调整
。
[2024-11-01T20:23:48.429][3.486s] GC(6) Summary Phase 0.011ms
时间:汇总阶段耗时
仅 0.011 毫秒。
[2024-11-01T20:23:48.429][3.486s] GC(6) Adjust Roots
Adjust Roots:开始调整根对象(Roots),更新指向存活对象的引用
。
[2024-11-01T20:23:48.433][3.490s] GC(6) Adjust Roots 4.043ms
时间:调整根阶段耗时
4.043 毫秒。
[2024-11-01T20:23:48.433][3.490s] GC(6) Compaction Phase
Compaction Phase: 开始压缩阶段,整理堆内存,减少内存碎片。
[2024-11-01T20:23:48.456][3.512s] GC(6) Compaction Phase 22.105ms
时间: 压缩阶段耗时 22.105 毫秒。
[2024-11-01T20:23:48.456][3.512s] GC(6) Post Compact
Post Compact:压缩后处理,进行后续的清理和整理
。
[2024-11-01T20:23:48.456][3.513s] GC(6) Post Compact 0.553ms
时间:压缩后处理阶段耗时
0.553 毫秒。
堆状态信息
[2024-11-01T20:23:48.456][3.513s] GC(6) PSYoungGen: 5911K(139264K)->0K(139264K) Eden: 0K(131072K)->0K(131072K) From: 5911K(8192K)->0K(8192K)
PSYoungGen: 年轻代的状态
。
5911K(139264K): GC 前年轻代使用了 5911 KB,最大为 139264 KB。
->0K(139264K): GC 后年轻代使用量降为 0 KB,表明所有对象都被回收。
Eden: 0K(131072K)->0K(131072K):Eden 区域的使用情况,GC 后也保持为 0 KB。
From: 5911K(8192K)->0K(8192K):From 区域在 GC 后清空
,从 5911 KB 降到 0 KB,最大为 8192 KB。
[2024-11-01T20:23:48.456][3.513s] GC(6) ParOldGen: 7619K(86016K)->12972K(86016K)
ParOldGen: 老年代的状态
。
7619K(86016K): GC 前老年代使用了 7619 KB,最大为 86016 KB。
->12972K(86016K): GC 后使用增加到 12972 KB,表明老年代的对象存活并增加了使用量。
[2024-11-01T20:23:48.456][3.513s] GC(6) Metaspace: 21093K(21504K)->21093K(21504K) NonClass: 18547K(18816K)->18547K(18816K) Class: 2546K(2688K)->2546K(2688K)
Metaspace: 类元数据的状态
。
21093K(21504K): GC 前使用了 21093 KB,最大为 21504 KB,GC 后保持不变。
NonClass: 18547K(18816K)->18547K(18816K): 非类元数据的使用保持不变。
Class: 2546K(2688K)->2546K(2688K): 类元数据的使用也没有变化。
GC 总结信息
[2024-11-01T20:23:48.456][3.513s] GC(6) Pause Full (Metadata GC Threshold) 13M->12M(220M) 51.695ms
Pause Full (Metadata GC Threshold): 说明这是一次由于类元数据阈值触发的【全堆 GC】
。
13M->12M(220M): 垃圾收集前总堆内存使用为 13 MB,GC 后减少到 12 MB,总堆大小为 220 MB。
51.695ms: 本次垃圾回收的总耗时为 51.695 毫秒。
总体时间统计
[2024-11-01T20:23:48.456][3.513s] GC(6) User=0.09s Sys=0.00s Real=0.05s
User=0.09s: 用户态时间为 0.09 秒。
Sys=0.00s: 系统态时间为 0 秒。
Real=0.05s: 实际经过时间为 0.05 秒,表示从 GC 开始到结束的真实时间。Using G1
Young GC
[2024-11-01T19:53:30.051+0800][0.322s] GC(1) Pause Young (Normal) (G1 Evacuation Pause)
[2024-11-01T19:53:30.051+0800][0.322s] GC(1) Using 2 workers of 2 for evacuation
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Pre Evacuate Collection Set: 0.1ms
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Merge Heap Roots: 0.0ms
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Evacuate Collection Set: 3.0ms
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Post Evacuate Collection Set: 0.2ms
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Other: 0.1ms
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Eden regions: 9->0(32)
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Survivor regions: 1->2(2)
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Old regions: 2->3
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Humongous regions: 0->0
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Metaspace: 1681K(1920K)->1681K(1920K) NonClass: 1501K(1600K)->1501K(1600K) Class: 180K(320K)->180K(320K)
[2024-11-01T19:53:30.054+0800][0.326s] GC(1) Pause Young (Normal) (G1 Evacuation Pause) 10M->3M(128M) 3.471ms
开始的 GC 信息
[2024-11-01T19:53:30.051+0800][0.322s] GC(1) Pause Young (Normal) (G1 Evacuation Pause)
时间戳: 2024-11-01T19:53:30.051+0800 表示 GC 发生的时间。
GC(1): 第 1 次 GC,标识该回收事件。
Pause Young (Normal): 表示这是一次正常的年轻代暂停 GC。
(G1 Evacuation Pause): 表示这是 G1 垃圾收集器的清除(Evacuation)暂停。
GC 工作信息
[2024-11-01T19:53:30.051+0800][0.322s] GC(1) Using 2 workers of 2 for evacuation
Using 2 workers of 2 for evacuation: 在清除过程中使用了 2 个工作线程,表示并行处理。
GC 阶段信息
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Pre Evacuate Collection Set: 0.1ms
Pre Evacuate Collection Set:清除前的准备阶段
,耗时 0.1 毫秒。
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Merge Heap Roots: 0.0ms
Merge Heap Roots:合并堆根对象的过程
,耗时 0.0 毫秒,表示没有任何时间开销。
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Evacuate Collection Set: 3.0ms
Evacuate Collection Set:实际的清除过程
,耗时 3.0 毫秒,主要负责将存活的对象从 Eden 区域迁移到 Survivor 区域或老年代。
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Post Evacuate Collection Set: 0.2ms
Post Evacuate Collection Set:清除后的处理
,耗时 0.2 毫秒。
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Other: 0.1ms
Other:其他未分类的开销
,耗时 0.1 毫秒。
堆区域状态信息
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Eden regions: 9->0(32)
Eden regions:
9->0(32): GC 前 Eden 区域有 9 个,GC 后清空为 0 个,最大支持 32 个区域。表明所有对象在 Eden 区域都被清除。
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Survivor regions: 1->2(2)
Survivor regions:
1->2(2): GC 前 Survivor 区域有 1 个,GC 后增加到 2 个,最大支持 2 个区域。表明有存活的对象被迁移到 Survivor 区域。
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Old regions: 2->3
Old regions:
2->3: GC 前老年代区域有 2 个,GC 后增加到 3 个,表明老年代有新的对象被晋升。
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Humongous regions: 0->0
Humongous regions:
0->0: GC 前后均为 0,表示没有大对象(超出 32KB 的对象)。
Metaspace 状态信息
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Metaspace: 1681K(1920K)->1681K(1920K) NonClass: 1501K(1600K)->1501K(1600K) Class: 180K(320K)->180K(320K)
Metaspace:
1681K(1920K): GC 前使用了 1681 KB,最大为 1920 KB,GC 后保持不变。
NonClass: 1501K(1600K)->1501K(1600K): 非类元数据的使用没有变化。
Class: 180K(320K)->180K(320K): 类元数据的使用也没有变化。
GC 总结信息
[2024-11-01T19:53:30.054+0800][0.325s] GC(1) Pause Young (Normal) (G1 Evacuation Pause) 10M->3M(128M) 3.471ms
Pause Young (Normal) (G1 Evacuation Pause): 说明这是一次正常的年轻代回收,采用 G1 收集器的清除模式。
10M->3M(128M): 垃圾回收前总堆内存使用为 10 MB,GC 后减少到 3 MB,总堆大小为 128 MB。
3.471ms: 本次垃圾回收的总耗时为 3.471 毫秒。G1 垃圾回收的并发标记(Concurrent Mark Cycle)过程
[2024-11-01T19:53:32.774+0800][3.045s] GC(6) Concurrent Mark Cycle
[2024-11-01T19:53:32.774+0800][3.045s] GC(6) Concurrent Scan Root Regions
[2024-11-01T19:53:32.788+0800][3.060s] GC(6) Concurrent Scan Root Regions 14.377ms
[2024-11-01T19:53:32.788+0800][3.060s] GC(6) Concurrent Mark
[2024-11-01T19:53:32.788+0800][3.060s] GC(6) Concurrent Mark From Roots
[2024-11-01T19:53:32.788+0800][3.060s] GC(6) Using 1 workers of 1 for marking
[2024-11-01T19:53:32.794+0800][3.065s] GC(6) Concurrent Mark From Roots 5.669ms
[2024-11-01T19:53:32.794+0800][3.065s] GC(6) Concurrent Preclean
[2024-11-01T19:53:32.794+0800][3.065s] GC(6) Concurrent Preclean 0.017ms
[2024-11-01T19:53:32.794+0800][3.066s] GC(6) Pause Remark
[2024-11-01T19:53:32.799+0800][3.070s] GC(6) Pause Remark 14M->14M(57M) 4.245ms
[2024-11-01T19:53:32.799+0800][3.070s] GC(6) User=0.01s Sys=0.00s Real=0.01s
[2024-11-01T19:53:32.799+0800][3.070s] GC(6) Concurrent Mark 10.630ms
[2024-11-01T19:53:32.799+0800][3.070s] GC(6) Concurrent Rebuild Remembered Sets and Scrub Regions
[2024-11-01T19:53:32.808+0800][3.080s] GC(6) Concurrent Rebuild Remembered Sets and Scrub Regions 9.520ms
[2024-11-01T19:53:32.808+0800][3.080s] GC(6) Pause Cleanup
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Pause Cleanup 15M->15M(57M) 0.064ms
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) User=0.00s Sys=0.00s Real=0.00s
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Concurrent Clear Claimed Marks
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Concurrent Clear Claimed Marks 0.019ms
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Concurrent Cleanup for Next Mark
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Concurrent Cleanup for Next Mark 0.348ms
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Concurrent Mark Cycle 35.205ms
开始的 GC 信息
[2024-11-01T19:53:32.774+0800][3.045s] GC(6) Concurrent Mark Cycle
时间戳: 2024-11-01T19:53:32.774+0800 表示 GC 发生的时间。
GC(6): 第 6 次 GC,标识该回收事件。
Concurrent Mark Cycle: 表示这是一次并发标记周期,用于标记堆中活跃的对象。
并发扫描根区域
[2024-11-01T19:53:32.774+0800][3.045s] GC(6) Concurrent Scan Root Regions
Concurrent Scan Root Regions:开始并发扫描根区域,以识别根对象,通常是全局变量、线程栈中的对象等
。
[2024-11-01T19:53:32.788+0800][3.060s] GC(6) Concurrent Scan Root Regions 14.377ms
Concurrent Scan Root Regions 14.377ms:执行根区域的并发扫描耗时
14.377 毫秒。
并发标记过程
[2024-11-01T19:53:32.788+0800][3.060s] GC(6) Concurrent Mark
Concurrent Mark:开始并发标记阶段,识别存活的对象
。
[2024-11-01T19:53:32.788+0800][3.060s] GC(6) Concurrent Mark From Roots
Concurrent Mark From Roots:从根对象开始标记存活对象
。
[2024-11-01T19:53:32.788+0800][3.060s] GC(6) Using 1 workers of 1 for marking
Using 1 workers of 1 for marking: 使用 1 个工作线程进行标记。
[2024-11-01T19:53:32.794+0800][3.065s] GC(6) Concurrent Mark From Roots 5.669ms
Concurrent Mark From Roots 5.669ms: 从根对象进行标记的过程耗时
5.669 毫秒。
[2024-11-01T19:53:32.794+0800][3.065s] GC(6) Concurrent Preclean
Concurrent Preclean:进行并发预清理
,处理在并发标记期间的某些对象,帮助减少后续的停顿时间。
[2024-11-01T19:53:32.794+0800][3.065s] GC(6) Concurrent Preclean 0.017ms
Concurrent Preclean 0.017ms: 预清理耗时 0.017 毫秒。
暂停标记阶段
[2024-11-01T19:53:32.794+0800][3.066s] GC(6) Pause Remark
Pause Remark:开始暂停标记阶段
,进行最后的标记处理。
[2024-11-01T19:53:32.799+0800][3.070s] GC(6) Pause Remark 14M->14M(57M) 4.245ms
Pause Remark 14M->14M(57M): 标记过程中堆内存使用前后均为 14 MB,最大堆内存为 57 MB,表示没有发生变化。
4.245ms: 本次暂停标记的耗时为
4.245 毫秒。
并发标记的总耗时
[2024-11-01T19:53:32.799+0800][3.070s] GC(6) Concurrent Mark 10.630ms
Concurrent Mark 10.630ms: 并发标记阶段的总耗时为 10.630 毫秒。
重建记忆集和清理区域
[2024-11-01T19:53:32.799+0800][3.070s] GC(6) Concurrent Rebuild Remembered Sets and Scrub Regions
Concurrent Rebuild Remembered Sets and Scrub Regions: 重建记忆集和清理区域。
[2024-11-01T19:53:32.808+0800][3.080s] GC(6) Concurrent Rebuild Remembered Sets and Scrub Regions 9.520ms
Concurrent Rebuild Remembered Sets and Scrub Regions 9.520ms: 重建记忆集和清理区域的耗时为 9.520 毫秒。
清理阶段
[2024-11-01T19:53:32.808+0800][3.080s] GC(6) Pause Cleanup
Pause Cleanup: 开始清理阶段,负责清理不再使用的对象。
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Pause Cleanup 15M->15M(57M) 0.064ms
Pause Cleanup 15M->15M(57M): 清理过程中堆内存使用前后均为 15 MB,最大堆内存为 57 MB,表示没有变化。
0.064ms: 本次清理的耗时为 0.064 毫秒。
清除标记和准备下一次标记
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Concurrent Clear Claimed Marks
Concurrent Clear Claimed Marks: 并发清除已声明的标记。
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Concurrent Clear Claimed Marks 0.019ms
Concurrent Clear Claimed Marks 0.019ms: 清除标记的耗时为 0.019 毫秒。
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Concurrent Cleanup for Next Mark
Concurrent Cleanup for Next Mark: 准备下一次标记的并发清理。
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Concurrent Cleanup for Next Mark 0.348ms
Concurrent Cleanup for Next Mark 0.348ms: 准备工作的耗时为 0.348 毫秒。
总结信息
[2024-11-01T19:53:32.809+0800][3.080s] GC(6) Concurrent Mark Cycle 35.205ms
Concurrent Mark Cycle 35.205ms: 整个并发标记周期的总耗时为 35.205 毫秒。
jvm 常用工具 (待完善)
jvm自带:jstat、jmap
第三方:mat、gcviewer
自带指令(详细内容待补充)
jps #查看所有的java进程
- jstack
- jmap
- jstat
jstat -gc <pid> 1000 10
#得到以下数据
S0C | S1C | S0U | S1U | EC | EU | OC | OU | MC | MU |
---|---|---|---|---|---|---|---|---|---|
0.0 | 6144.0 | 0.0 | 4712.7 | 73728.0 | 0.0 | 57344.0 | 34393.5 | 61132.0 | 59888.7 |
CCSU | YGC | YGCT | FGC | FGCT | CGC | CGCT | GCT |
---|---|---|---|---|---|---|---|
7372.0 | 6980.1 | 19 | 0.172 | 0 | 0.000 | 6 | 0.019 |
S0C: survivor 0区域的容量,以KB为单位
S1C: survivor 1区域的容量,以KB为单位
S0U: survivor 0区域的使用大小,以KB为单位
S1U: survivor 1区域的使用大小,以KB为单位
EC: Eden区域的容量,以KB为单位
EU: Eden区域的使用,以KB为单位
MC: Metaspace元数据区的 Committed Size,以KB为单位
MU: Metaspace元数据区的使用大小,以KB为单位
CCSC: Compressed class的Committed Size,以KB为单位
CCSU: Compressed class的使用大小,以KB为单位
OC: old区域的容量,以KB为单位
OU: old区域的使用,以KB为单位
YGC: young generation(年轻代)的GC次数
YGCT: young generation(年轻代)的GC消耗时间
FGC: full GC的次数
FGCT: full GC的消耗时间
CGC: 并发GC次数(G1 gc)
CGCT: 并发GC的消耗时间(G1 gc)
GCT: GC总消耗时间
- jhat
常用启动参数
-Xms:设置堆初始大小
-Xmx:设置堆最大大小
-Xss:设置每个线程栈大小
-Xmn:设置年轻代大小
-XX:NewRatio = 3:设置年轻代(Eden、S0、S1)与老年代的比值
-XX:SurvivorRatio = 6 :设置年轻代中Eden区与Survivor区的大小比值
-XX:NewSize:设置年轻代初始值
-XX:MaxNewSize:设置年轻代最大值
-XX:MaxTenuringThreshold:设置垃圾最大年龄
-XX:+UseG1GC:使用 G1 垃圾回收器
-XX:+UseParallelGC:使用并行垃圾回收器
-XX:ParallelGCThreads = 5:配置并行收集器的线程数
-XX:MaxGCPauseMillis=N:N为希望暂停时间(毫秒),默认无
-XX:MetaspaceSize:设置 Metaspace 的初始大小
-XX:MaxMetaspaceSize:设置 Metaspace 的最大值
-XX:+PrintGCDetails:打印垃圾回收详细信息
-XX:+HeapDumpOnOutOfMemoryError:内存溢出时生成堆转储
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>