JVM基础

Larsjvmjvm大约 7 分钟

儒猿JVM FREEopen in new window

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做计划回收

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核心算法

采用三色标记 + Incremental Update

参考: https://www.cnblogs.com/ZT-666/p/15811798.htmlopen in new window

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