JVM——jinfo命令使用及GC日志分析


技術公眾號:后端技術解憂鋪
關注微信公眾號:CodingTechWork,一起學習進步。

引言

  在我們的日常開發過程中,可能不怎么關注JVM的GC,但是一旦我們開發的程序上線后,伴隨着運行時間的拉長,各種線上問題就出現了,比如內存溢出,比如機器cpu和memory耗盡,除了查看程序的日志是否報錯拋異常,排查是否有bug,而有時候就得先看看程序運行所需要的內存是否足夠。這時,我們就需要GC日志來輔助查看。

GC類型

參數 新生代GC 老年代GC
-XX:+UseSerialGC 虛擬機運行在Client模式的默認值,Serial 串行GC Serial Old串行GC
-XX:+UseParallelGC 虛擬機運行在Server模式的默認值,Parallel Scavenge並行回收GC Parallel Old並行GC
-XX:+UseConcMarkSweepGC ParNew並行GC CMS並發GC,當出現Concurrent Mode Failure時采用Serial Old串行GC作為備用垃圾收集器
-XX:+UseParNewGC ParNew並行GC Serial Old串行GC
-XX:+UseParallelOldGC Parallel Scavenge並行回收GC Parallel Old並行GC
-XX:+UseConcMarkSweepGC
-XX:+UseParaNewGC
Serial串行GC CMS並發GC,當出現Concurrent Mode Failure時采用Serial Old串行GC

jinfo使用

介紹

  jinfo全稱Java Configuration info,用於實時查看和調整JVM配置參數。

語法參數

[linux@01 ~]$ jinfo -help
Usage:
    jinfo [option] <pid>
        (to connect to running process)
    jinfo [option] <executable <core>
        (to connect to a core file)
    jinfo [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

where <option> is one of:
    -flag <name>         to print the value of the named VM flag
    -flag [+|-]<name>    to enable or disable the named VM flag
    -flag <name>=<value> to set the named VM flag to the given value
    -flags               to print VM flags
    -sysprops            to print Java system properties
    <no option>          to print both of the above
    -h | -help           to print this help message

示例

查看JVM運行參數

[linux@01 ~]$ jinfo -flags 15764
Attaching to process ID 15764, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.65-b01
Non-default VM flags: -XX:CICompilerCount=12 -XX:InitialHeapSize=526385152 -XX:MaxHeapSize=8392802304 -XX:MaxNewSize=2797600768 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=175112192 -XX:OldSize=351272960 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 
Command line:  -Djava.util.logging.config.file=/home/s1/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -XX:MaxPermSize=1024m -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -agentlib:jdwp=transport=dt_socket,address=8017,server=y,suspend=n -Ds1.conf.dir=/home/s1/conf -Dservice01.logs.dir=/home/s1/logs -Ds1.home.dir=/home/s1-Ds1.server.port=7005 -Ds1.http.port=7010 -Ds1.redirect.port=7443 -Ds1.ajp.port=7009 -Dcas.server.ip=10.x.x.x -Dcas.server.port=7010 -Dbdoc.http.ip=10.x.x.x -Ds1.mysql.address=10.x.x.x:3306 -Ds1.mysql.database.name=db01 -Ds1.mysql.user=s1 -Ds1.mysql.passwd=123456 -Dcatalina.base=/home/s1/tomcat -Dcatalina.home=/home/s1/tomcat -Djava.io.tmpdir=/home/s1/tomcat/temp

查看指定參數是否開啟

[linux@01 ~]$ jinfo -flag UseSerialGC 15764
-XX:-UseSerialGC
[linux@01 ~]$
[linux@01 ~]$ jinfo -flag UseParNewGC 15764
-XX:-UseParNewGC
[linux@01 ~]$
[linux@01 ~]$ jinfo -flag UseConcMarkSweepGC 15764
-XX:-UseConcMarkSweepGC
[linux@01 ~]$
[linux@01 ~]$ jinfo -flag UseParallelGC 15764
-XX:+UseParallelGC
[linux@01 ~]$
[linux@01 ~]$ jinfo -flag UseParallelOldGC 15764
-XX:+UseParallelOldGC

查看指定配置參數值

[linux@01 ~]$ jinfo -flag MaxHeapSize 15764
-XX:MaxHeapSize=8392802304

增刪配置參數

[linux@01 ~]$ jinfo -flag +PrintGC 17984
[linux@01 ~]$ jinfo -flag PrintGC 17984
-XX:+PrintGC

GC日志

GC日志常用參數

參數 說明
-XX:+PrintGC 輸出GC日志
-XX:+PrintGCDetails 輸出GC詳細日志
-XX:+PrintGCDateStamps 以日期的形式輸出GC的時間戳,如2021-01-14T20:20:59.125+0800
-XX:+PrintGCTimeStamps 以基准時間的形式輸出GC的時間戳
-XX:+PrintHeapAtGC 在進行GC的前后打印出堆的信息
-XX:+PrintGCApplicationConcurrentTime 打印應用程序執行時間
-XX:+PrintGCApplicationStoppedTime 打印應用程序因GC而產生的停頓時間
-Xloggc:/var/logs/gc.log 以文件的方式保存GC日志

對象優先在Eden分配

  我們先看一下gc的一個分代處理。

Eden分配

  大多數情況下,對象在新生代Eden區中分配,當Eden區沒有足夠空間進行分配時,VM將發起一次Minor GC。
  新生代總可用空間:Eden區 + 1個Survivor區的總容量

新生代和老年代GC

新生代GC(Minor GC)和老年代GC(Major GC/ Full GC)

  • 新生代GC:Minor GC指發生在新生代的垃圾收集動作,Java對象大多是朝生夕滅,Minor GC非常頻繁,回收速度快。回收新生代,新生代中分為Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中的一塊Survivor。默認Eden : Survivor=8:1,Survivor不夠時,老年代內存分配擔保。新生代中,每次垃圾收集時都發現有大批對象死去,少量存活,選用復制算法。
  • 老年代GC:Major GC指發生在老年代的GC,出現此GC,經常會伴隨至少一次Minor GC,一般Major GC比Minor GC慢10倍以上。老年代中,對象存活率高、沒有額外空間進行分配擔保,使用“標記-清理”或者“標記-整理”。

GC日志示例分析

   [Eden: 5888.0M(5888.0M)->0.0B(6592.0M) Survivors: 640.0M->672.0M Heap: 27.4G(32.0G)->21.7G(32.0G)]
 [Times: user=2.55 sys=0.04, real=0.14 secs] 
  • Eden: 5888.0M(5888.0M)->0.0B(6592.0M):表示發生GC前,Eden空間大小是5888.0M,且空間全部被占用。發生GC發生之后,年輕代空間(Young Generation)下降到0,Eden空間增長到6592.0M。
  • Survivors: 640.0M->672.0M:表示發生GC前,Survivor存活區空間是640.0M。發生GC后,存活區空間增長到672.0M,表明對象從年輕代(Young Generation)提升到存活區空間(Survivor space)
  • Heap: 27.4G(32.0G)->21.7G(32.0G):表示發生GC前,Heap堆空間大小是32.0G,被占用27.4G。發生GC后,堆大小仍然為32.0G,堆占用了21.7G(即(27.4G-21.7G)的對象被垃圾回收了)。
  • [Times: user=2.55 sys=0.04, real=0.14 secs]
    1)user表示CPU工作在用戶態所花費的時間;
    2)sys表示CPU工作在內核態所花費的時間;
    3)real表示GC事件所花費的總時間。
    一般,user+sys就是CPU花費的實際時間。
    a)如果進程工作在多線程的環境下(垃圾回收通過並發執行),一般該值會超過real,即:user + sys > real
    b)如果出現串行的垃圾回收,有可能觀察到user + sys = real
    c)如果CPU資源匱乏、I/O操作繁忙,GC就會出現等待的情況,這時會出現user + sys < real


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM