JVM基础
jvmjvm大约 7 分钟
JVM内存结构
- 虚拟机栈:线程独享()
- 程序计数器:线程独享
- 元空间:
- 堆:
- 本地方法栈
垃圾回收器
- Young
- Serial:单线程、STW、复制清除
- ParNew:多线程、STW、复制清除
- ParallelScavenge:多线程、STW
- Old
- SerialOld:单线程、STW、标记整理
- ParallelOld:多线程、STW、标记整理
- CMS:多线程并发、最短STW
- 初始标记:STW
- 并发标记
- 重新标记:STW
- 并发清除
- ALL
- G1:将内存分为3类,每类分为很多小块(region),分类多块,可以让回收并行
- 初始标记:STW、GCroot
- 并发标记:
- 重新标记:STW
- 筛选回收:根据预期的STW,针对所有Region做计划回收
- G1:将内存分为3类,每类分为很多小块(region),分类多块,可以让回收并行
CMS
垃圾回收JVM参数
-Dappname=guide-core-app-service
-Xms3072M #堆初始化大小
-Xmx3072M #最大堆大小
-Xmn1843M #年轻代大小
-Xss1M #每个线程的虚拟机栈大小
-XX:MetaspaceSize=256M #元空间大小
-XX:MaxMetaspaceSize=256M #最大元空间大小
-XX:ParallelGCThreads=2 #并发收集线程数,STW阶段使用线程数,默认是总核数的60%
-XX:ConcGCThreads=2 #并发回收垃圾的线程数。默认是总核数的12.5%,8核CPU默认是1。调大后GC变快,但会占用程序运行时的CPU资源,吞吐会受到影响。
-Djava.util.concurrent.ForkJoinPool.common.parallelism=2
-XX:CICompilerCount=2 #并发编译线程数
-XX:+UseConcMarkSweepGC #使用cms收集器
-XX:+CMSParallelInitialMarkEnabled #cms多线程并发执行初始标记
-XX:+CMSParallelRemarkEnabled #cms重新标记前触发一次YGC,以此减少重新标记耗时
-XX:+UseFastAccessorMethods #冗余代码转为本地代码(get/set)
-XX:+UseCMSInitiatingOccupancyOnly #老年代回收阀值手动设置
-XX:CMSInitiatingOccupancyFraction=70 #老年代回收阀值
-XX:+HeapDumpOnOutOfMemoryError #发生oom自动生成dump文件
-XX:HeapDumpPath=/data/share/guide-core-app-service_dump.log #dump文件目录
-Duser.timezone=GMT+8 -Djava.security.egd=/dev/urandom
-Dfile.encoding=UTF-8 -Djava.net.preferIPv4Stack=true
-Djava.net.preferIPv4Addresses -javaagent:/usr/src/jacocoagent.jar=includes=*,output=tcpserver,append=false,address=*,port=20001
提示
将Xms和Xmx设为一样的值。如果虚拟机启动时设置使用的内存比较小,这个时候又需要初始化很多对象,虚拟机就必须重复地增加内存。
- 初始标记(CMS-initial-mark):STW
- 并发标记(CMS-concurrent-mark)
- 重新标记(CMS Final Remark):STW
- 并发清除(CMS-concurrent-sweep)
//younggc
[GC (Allocation Failure) 2023-01-16T12:51:48.760-0800: 4085.648: [ParNew: 73727K->73727K(73728K), 0.0001147 secs]2023-01-16T12:51:48.760-0800: 4085.648: [CMS: 71679K->71679K(71680K), 0.3253975 secs] 145407K->97104K(145408K), [Metaspace: 105905K->105905K(1146880K)], 0.3258200 secs] [Times: user=0.30 sys=0.02, real=0.32 secs]
//初始标记:只扫描gcroot直接关联到的对象进行标记,会暂停用户线程(STW),速度很快【20ms】
[GC (CMS Initial Mark) [1 CMS-initial-mark: 71680K(71680K)] 104274K(145408K), 0.0267617 secs] [Times: user=0.04 sys=0.00, real=0.02 secs]
//并发标记:从直接关联对象并发遍历所有老年代对象,寻找存活对象进行标记【较慢,但不暂停用户线程】
[CMS-concurrent-mark-start]
[CMS-concurrent-mark: 0.042/0.042 secs] [Times: user=0.08 sys=0.01, real=0.04 secs]
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[CMS-concurrent-abortable-preclean-start]
[CMS-concurrent-abortable-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
//重新标记:修正并发标记期间存活状态发生变化的对象,会暂停用户线程(STW),速度较快【60ms】
[GC (CMS Final Remark) [YG occupancy: 32594 K (73728 K)]
[Rescan (parallel) , 0.0280437 secs]
[weak refs processing, 0.0018868 secs]
[class unloading, 0.0125393 secs]
[scrub symbol table, 0.0230813 secs]
[scrub string table, 0.0008489 secs]
[1 CMS-remark: 71680K(71680K)] 104274K(145408K), 0.0670251 secs] [Times: user=0.12 sys=0.00, real=0.06 secs]
//并发清除:清除
[CMS-concurrent-sweep-start]
[CMS-concurrent-sweep: 0.025/0.025 secs] [Times: user=0.02 sys=0.00, real=0.03 secs]
[CMS-concurrent-reset-start]
[CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
CMS优缺点:
- 优点:并发收集、低停顿时间
- 缺点:
- 标记清除(mark-sweep)导致空间碎片,解决方案:-XX:CMSFullGCsBeforeCompaction参数(默认为0 指的是经过多少次FGC才进行碎片整理)
- 并发标记期间产生新的垃圾对象,无法参与本次收集,存在浮动垃圾,如果浮动垃圾大于老年代剩余空间,会导致FGC,解决方案:降低触发CMS的阈值,–XX:CMSInitiatingOccupancyFraction 92% 可以降低这个值,让CMS保持老年代足够的空间
CMS参考文献
G1
-Dappname=guide-service
-Xms6144M -Xmx6144M -Xss1M
-XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=512M
-XX:ParallelGCThreads=4 -XX:ConcGCThreads=4
-Djava.util.concurrent.ForkJoinPool.common.parallelism=4
-XX:CICompilerCount=3
-XX:+UseG1GC -XX:MaxGCPauseMillis=200
-XX:+ParallelRefProcEnabled
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/data/share/guide-service_dump.log
-Duser.timezone=GMT+8 -Djava.security.egd=/dev/urandom
-Dfile.encoding=UTF-8 -Djava.net.preferIPv4Stack=true
-Djava.net.preferIPv4Addresses
- 初始标记(initial-mark):STW
- 并发标记(concurrent-mark)
- 最终标记(Finalize Marking,):STW
- 筛选回收:STW
//young gc
2023-01-16T14:28:25.240-0800: 11294.563: [GC pause (G1 Evacuation Pause) (young) (initial-mark), 0.0122643 secs]
[Parallel Time: 7.9 ms, GC Workers: 8]
[GC Worker Start (ms): Min: 11294564.0, Avg: 11294564.1, Max: 11294564.3, Diff: 0.2]
[Ext Root Scanning (ms): Min: 2.7, Avg: 3.3, Max: 5.7, Diff: 2.9, Sum: 26.2]
[Update RS (ms): Min: 0.0, Avg: 0.6, Max: 2.8, Diff: 2.8, Sum: 4.7]
[Processed Buffers: Min: 0, Avg: 6.0, Max: 16, Diff: 16, Sum: 48]
[Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
[Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
[Object Copy (ms): Min: 0.0, Avg: 0.8, Max: 2.0, Diff: 2.0, Sum: 6.0]
[Termination (ms): Min: 0.0, Avg: 1.6, Max: 3.0, Diff: 3.0, Sum: 13.0]
[Termination Attempts: Min: 1, Avg: 1.6, Max: 3, Diff: 2, Sum: 13]
[GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
[GC Worker Total (ms): Min: 5.7, Avg: 6.3, Max: 7.0, Diff: 1.3, Sum: 50.1]
[GC Worker End (ms): Min: 11294569.9, Avg: 11294570.4, Max: 11294571.1, Diff: 1.2]
[Code Root Fixup: 0.1 ms]
[Code Root Purge: 0.0 ms]
[Clear CT: 0.1 ms]
[Other: 4.1 ms]
[Choose CSet: 0.0 ms]
[Ref Proc: 3.6 ms]
[Ref Enq: 0.1 ms]
[Redirty Cards: 0.1 ms]
[Humongous Register: 0.0 ms]
[Humongous Reclaim: 0.0 ms]
[Free CSet: 0.0 ms]
[Eden: 8192.0K(8192.0K)->0.0B(8192.0K) Survivors: 1024.0K->1024.0K Heap: 132.4M(150.0M)->124.7M(150.0M)]
[Times: user=0.03 sys=0.01, real=0.01 secs]
2023-01-16T14:28:25.252-0800: 11294.576: [GC concurrent-root-region-scan-start]
2023-01-16T14:28:25.255-0800: 11294.578: [GC concurrent-root-region-scan-end, 0.0029098 secs]
2023-01-16T14:28:25.255-0800: 11294.578: [GC concurrent-mark-start]
2023-01-16T14:28:25.344-0800: 11294.667: [GC concurrent-mark-end, 0.0888734 secs]
2023-01-16T14:28:25.345-0800: 11294.668: [GC remark
2023-01-16T14:28:25.345-0800: 11294.668: [Finalize Marking, 0.0020186 secs]
2023-01-16T14:28:25.347-0800: 11294.670: [GC ref-proc, 0.0040022 secs]
2023-01-16T14:28:25.351-0800: 11294.674: [Unloading, 0.0417962 secs], 0.0481867 secs]
[Times: user=0.12 sys=0.03, real=0.05 secs]
2023-01-16T14:28:25.394-0800: 11294.718: [GC cleanup 125M->125M(150M), 0.0009046 secs]
[Times: user=0.00 sys=0.00, real=0.00 secs]
//混合回收
2023-01-16T14:28:32.255-0800: 11301.579: [GC pause (G1 Evacuation Pause) (mixed), 0.0139194 secs]
[Parallel Time: 9.2 ms, GC Workers: 8]
[GC Worker Start (ms): Min: 11301578.7, Avg: 11301578.8, Max: 11301579.0, Diff: 0.2]
[Ext Root Scanning (ms): Min: 0.8, Avg: 1.2, Max: 3.1, Diff: 2.3, Sum: 9.6]
[Update RS (ms): Min: 0.0, Avg: 0.3, Max: 0.6, Diff: 0.6, Sum: 2.7]
[Processed Buffers: Min: 0, Avg: 5.9, Max: 22, Diff: 22, Sum: 47]
[Scan RS (ms): Min: 0.0, Avg: 0.6, Max: 1.1, Diff: 1.1, Sum: 4.6]
[Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
[Object Copy (ms): Min: 0.2, Avg: 1.1, Max: 1.5, Diff: 1.3, Sum: 9.2]
[Termination (ms): Min: 0.0, Avg: 2.2, Max: 5.9, Diff: 5.9, Sum: 17.8]
[Termination Attempts: Min: 1, Avg: 2.5, Max: 5, Diff: 4, Sum: 20]
[GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.2]
[GC Worker Total (ms): Min: 3.3, Avg: 5.5, Max: 9.2, Diff: 5.9, Sum: 44.1]
[GC Worker End (ms): Min: 11301582.2, Avg: 11301584.3, Max: 11301587.9, Diff: 5.8]
[Code Root Fixup: 0.2 ms]
[Code Root Purge: 0.0 ms]
[Clear CT: 0.2 ms]
[Other: 4.3 ms]
[Choose CSet: 0.0 ms]
[Ref Proc: 3.6 ms]
[Ref Enq: 0.2 ms]
[Redirty Cards: 0.2 ms]
[Humongous Register: 0.0 ms]
[Humongous Reclaim: 0.0 ms]
[Free CSet: 0.0 ms]
[Eden: 6144.0K(6144.0K)->0.0B(9216.0K) Survivors: 1024.0K->1024.0K Heap: 130.4M(150.0M)->124.6M(150.0M)]
[Times: user=0.02 sys=0.00, real=0.01 secs]
G1参考
ZGC
ZGC的核心特点是并发,GC过程中一直有新的对象产生。如何保证在GC完成之前,新产生的对象不会将堆占满,是ZGC参数调优的第一大目标
Dappname=guide-core-app-service
-Xms6144M
-Xmx6144M
-Xss1M
-XX:MetaspaceSize=256M
-XX:MaxMetaspaceSize=256M
-XX:ParallelGCThreads=3
-XX:ConcGCThreads=1
-Djava.util.concurrent.ForkJoinPool.common.parallelism=4
-XX:CICompilerCount=3
-XX:+UnlockExperimentalVMOptions
-XX:+UseZGC
-XX:ZAllocationSpikeTolerance=3 #ZGC触发自适应算法的修正系数,默认2,数值越大越早的触发
-XX:ZCollectionInterval=180 #ZGC发生的最小时间间隔,单位秒
-XX:+UnlockDiagnosticVMOptions
-XX:-ZProactive #关闭主动回收
-Xlog:safepoint,classhisto*=trace,age*,gc*=info:file=/data/share/guide-core-app-service_gc.log:time,tid,tags:filecount=5,filesize=20m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/data/share/guide-core-app-service_dump.log
-Duser.timezone=GMT+8
-Djava.security.egd=/dev/urandom
-Dfile.encoding=UTF-8
-Djava.net.preferIPv4Stack=true
-Djava.net.preferIPv4Addresses
会发生内存溢出的内存区域
- 元空间:.class被加载后存放的内存区域,如果超出上限会触发OOM
- 虚拟机栈:每个线程的栈大小默认1M,如果方法、局部变量、循环、递归过多也会导致OOM
- 堆:堆内存空间固定,存放对象总会到达上限,所以会出现OOM
Powered by Waline v2.14.1