JVM系列(四):JVM参数和可视化工具

JVM参数和监控工具介绍

   这篇文章主要有三部分内容,第一部分是介绍一些常用的java虚拟机的参数设置,第二部分是一些常用的用于监控虚拟机的一些命令,第三部分主要介绍一下根据这些监控命令集成的可视化工具。

JVM参数

   Jvm的参数主要分为三类,一类是标准参数,一类是-X参数,还有一类是 XX参数。

标准参数:标准参数中包括功能和输出的参数都是很稳定的,很可能在将来的 JVM 版本中不会改变,可以使用java命令检索出所有的标准参数。如-server 、 -version、-? -help等。

x参数:x参数在未来的JVM版本中可能发生改变,使用java -X命令可以查看x参数如下所示:

H:\IDEAworkSpace\springdemo>java -X
    -Xmixed           混合模式执行 (默认)
    -Xint             仅解释模式执行
    -Xbootclasspath:<用 ; 分隔的目录和 zip/jar 文件>
                      设置搜索路径以引导类和资源
    -Xbootclasspath/a:<用 ; 分隔的目录和 zip/jar 文件>
                      附加在引导类路径末尾
    -Xbootclasspath/p:<用 ; 分隔的目录和 zip/jar 文件>
                      置于引导类路径之前
    -Xdiag            显示附加诊断消息
    -Xnoclassgc       禁用类垃圾收集
    -Xincgc           启用增量垃圾收集
    -Xloggc:<file>    将 GC 状态记录在文件中 (带时间戳)
    -Xbatch           禁用后台编译
    -Xms<size>        设置初始 Java 堆大小
    -Xmx<size>        设置最大 Java 堆大小
    -Xss<size>        设置 Java 线程堆栈大小
    -Xprof            输出 cpu 配置文件数据
    -Xfuture          启用最严格的检查, 预期将来的默认值
    -Xrs              减少 Java/VM 对操作系统信号的使用 (请参阅文档)
    -Xcheck:jni       对 JNI 函数执行其他检查
    -Xshare:off       不尝试使用共享类数据
    -Xshare:auto      在可能的情况下使用共享类数据 (默认)
    -Xshare:on        要求使用共享类数据, 否则将失败。
    -XshowSettings    显示所有设置并继续
    -XshowSettings:all
                      显示所有设置并继续
    -XshowSettings:vm 显示所有与 vm 相关的设置并继续
    -XshowSettings:properties
                      显示所有属性设置并继续
    -XshowSettings:locale
                      显示所有与区域设置相关的设置并继续

-X 选项是非标准选项, 如有更改, 恕不另行通知。

并且我们注意到结尾有一句话,-X 是非标准的参数,更改来的话是不会另行通知的。
** XX 参数:**
   它们同样不是标准的,然而,在实际情况中 X 参数和 XX 参数并没有什么不同。X 参数的功能是十分稳定的,然而很多 XX 参数仍在实验当中(主要是 JVM 的开发者用于 debugging 和调优 JVM 自身的实现)。
-XX 参数是不稳定的参数,此类参数的设置很容易引起JVM 性能上的差异,使JVM存在极大的不稳定性。主要按以下规则分为三类:

  • 布尔类型参数值:
    -XX:+<option>'+'表示启用该选项
    -XX:-<option>'-'表示关闭该选项
  • 数字类型参数值:
    -XX:<option>=<number>给选项设置一个数字类型值,可跟随单位,如 -XX:MetaspaceSize=10M
  • 字符串类型参数值:
    -XX:<option>=<string>给选项设置一个字符串类型值,通常用于指定一个文件、路径或一系列命令列表。例如:-XX:HeapDumpPath=./dump.core

下面来介绍以下JVM调优方面常用的参数设置:
堆的内存设置参数:

参数含义说明
–Xms=512M设置堆的初始化大小为512M可简写为 –Xms512M
-Xmx=1024M设置堆的最大内存为1024M可简写为 -Xmx1024M
–Xmn=300M设置堆的新生代的大小为300M–Xmn300M ,Sun官方推荐配置为整个堆的3/8
–Xss512k设置堆栈大小为512kJDK5.0以后每个线程堆栈大小为1MB,以前每个线程堆栈大小为256K.
-XX:MetaspaceSize500M设置元数据区大小为500Mjdk1.8的元数据区
-XX:NewRatio=3设置年轻代和老年代的分配比值大小设置为3,则年轻代与年老代所占比值为1:3,年轻代占整个堆栈的1/4
-XX:SurvivorRatio=8设置年轻代中Eden区与Survivor区的大小比值设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。
-XX:NewSize=20M设置年轻代的大小新生代,吞吐量优先
-XX:OldSize=50M设置老年代大小老年代,吞吐量优先
-XX:+UseParallelGC使用UseParallelGC-XX:+UseParallelOldGC
-XX:+UseParallelOldGC使用UseParallelOldGC
-XX:+UseConcMarkSweepGC使用CMS老年代,停顿时间优先
-XX:+UseG1GC使用G1GC新生代,老年代,停顿时间优先
-XX:+HeapDumpOnOutOfMemoryError启动堆内存溢出打印当JVM堆内存发生溢出时,也就是OOM,自动生成dump文件
-XX:HeapDumpPath=heap.hprof指定堆内存溢出打印目录表示在当前目录生成一个heap.hprof文件
-XX:MaxTenuringThreshold=6提升年老代的最大临界值默认值为 15
-XX:G1HeapWastePercent允许的浪费堆空间的占比默认是10%,如果并发标记可回收的空间小于10%,则不会触发MixedGC。
-XX:MaxGCPauseMillis=20-XX:ConcGCThreads=nmsG1最大停顿时间暂停时间不能太小,太小的话就会导致出现G1跟不上垃圾产生的速度。最终退化成Full GC。所以对这个参数的调优是一个持续的过程,逐步调整到最佳状态。
-XX:ConcGCThreads=n并发垃圾收集器使用的线程数量默认值随JVM运行的平台不同而不同
-XX:G1MixedGCLiveThresholdPercent=65混合垃圾回收周期中要包括的旧区域设置占用率阈值默认占用率为 65%
-XX:G1OldCSetRegionThresholdPercent=1描述Mixed GC时,Old Region被加入到CSet中默认情况下,G1只把10%的Old Region加入到CSet中
XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStampsXloggc:$CATALINA_HOME/logs/gc.log打印出GC日志

常用的命令

jps

jps 命令类似与 linux 的 ps 命令,是一个显示当前所有java进程pid的命令。 通过 jps 命令可以方便地查看 Java 进程的启动类、传入参数和 Java 虚拟机参数等信息。
jps后面可以跟随多种命令:
-q:只输出进程 ID
-m:输出传入 main 方法的参数
-l:输出完全的包名,应用主类名,jar的完全路径名
-v:输出jvm参数
-V:输出通过flag文件传递到JVM中的参数

例如:

H:\IDEAworkSpace\springdemo>jps
13856 Jps
14848 Launcher
8656
19508 Bootstrap

jinfo 实时查看和调整JVM配置参数

   jinfo 是 JDK 自带的命令,可以用来查看正在运行的 java 应用程序的扩展参数,包括Java System属性和JVM命令行参数;也可以动态的修改正在运行的 JVM 一些参数。
jinfo的用法:

H:\IDEAworkSpace\springdemo>jinfo
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

例如:```markdown
H:\IDEAworkSpace\springdemo>jinfo -flag MaxHeapSize 19508
-XX:MaxHeapSize=2071986176

```

jstat

   Jstat是JDK自带的一个轻量级小工具,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。
jstat的用法:

H:\IDEAworkSpace\springdemo>jstat
invalid argument count
Usage: jstat -help|-options
       jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

Definitions:
  <option>      An option reported by the -options option
  <vmid>        Virtual Machine Identifier. A vmid takes the following form:
                     <lvmid>[@<hostname>[:<port>]]
                Where <lvmid> is the local vm identifier for the target
                Java virtual machine, typically a process id; <hostname> is
                the name of the host running the target Java virtual machine;
                and <port> is the port number for the rmiregistry on the
                target host. See the jvmstat documentation for a more complete
                description of the Virtual Machine Identifier.
  <lines>       Number of samples between header lines.
  <interval>    Sampling interval. The following forms are allowed:
                    <n>["ms"|"s"]
                Where <n> is an integer and the suffix specifies the units as
                milliseconds("ms") or seconds("s"). The default units are "ms".
  <count>       Number of samples to take before terminating.
  -J<flag>      Pass <flag> directly to the runtime system.

option: 参数选项
-t: 可以在打印的列加上Timestamp列,用于显示系统运行的时间
-h: 可以在周期性数据数据的时候,可以在指定输出多少行以后输出一次表头
vmid: Virtual Machine ID( 进程的 pid)
interval: 执行每次的间隔时间,单位为毫秒
count: 用于指定输出多少次记录,缺省则会一直打印

我们只需要输入命令如 jstat -options就能知道选项有哪些。

H:\IDEAworkSpace\springdemo>jstat -options
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation

如:查看垃圾收集信息,每秒打印一次,一共打印10次

C:\Users\Administrator>jstat -gc 19508 1000 10
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
21504.0 21504.0  0.0    0.0   199168.0 24266.2   72704.0    29918.3   21248.0 20697.8 2560.0 2291.5     11    0.124   1      0.097    0.221
21504.0 21504.0  0.0    0.0   199168.0 24266.2   72704.0    29918.3   21248.0 20697.8 2560.0 2291.5     11    0.124   1      0.097    0.221
21504.0 21504.0  0.0    0.0   199168.0 24266.2   72704.0    29918.3   21248.0 20697.8 2560.0 2291.5     11    0.124   1      0.097    0.221
21504.0 21504.0  0.0    0.0   199168.0 24266.2   72704.0    29918.3   21248.0 20697.8 2560.0 2291.5     11    0.124   1      0.097    0.221
21504.0 21504.0  0.0    0.0   199168.0 24266.2   72704.0    29918.3   21248.0 20697.8 2560.0 2291.5     11    0.124   1      0.097    0.221
21504.0 21504.0  0.0    0.0   199168.0 24266.2   72704.0    29918.3   21248.0 20697.8 2560.0 2291.5     11    0.124   1      0.097    0.221
21504.0 21504.0  0.0    0.0   199168.0 24266.2   72704.0    29918.3   21248.0 20697.8 2560.0 2291.5     11    0.124   1      0.097    0.221
21504.0 21504.0  0.0    0.0   199168.0 24266.2   72704.0    29918.3   21248.0 20697.8 2560.0 2291.5     11    0.124   1      0.097    0.221
21504.0 21504.0  0.0    0.0   199168.0 24266.2   72704.0    29918.3   21248.0 20697.8 2560.0 2291.5     11    0.124   1      0.097    0.221
21504.0 21504.0  0.0    0.0   199168.0 24266.2   72704.0    29918.3   21248.0 20697.8 2560.0 2291.5     11    0.124   1      0.097    0.221

jstack

jstack命令用来查看线程堆栈信息:
例如:

H:\IDEAworkSpace\springdemo>jps
8656
15396 Jps
19508 Bootstrap
19752 Launcher

H:\IDEAworkSpace\springdemo>jps
8656
18980 Launcher
18904 DeadLockDemo
13356 Jps

H:\IDEAworkSpace\springdemo>jstack 18904
2020-01-05 16:00:44
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.74-b02 mixed mode):

"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x0000000002f43800 nid=0x10a0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #13 prio=5 os_prio=0 tid=0x000000001acff000 nid=0x4b74 waiting for monitor entry [0x000000001b4de000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at threaddemo.DeadLockDemo.lambda$deadLock$1(DeadLockDemo.java:34)
        - waiting to lock <0x00000000d6f996c0> (a java.lang.String)
        - locked <0x00000000d6f996f0> (a java.lang.String)
        at threaddemo.DeadLockDemo$$Lambda$2/1702297201.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)

"Thread-0" #12 prio=5 os_prio=0 tid=0x000000001acfc000 nid=0x38b0 waiting for monitor entry [0x000000001b3df000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at threaddemo.DeadLockDemo.lambda$deadLock$0(DeadLockDemo.java:24)
        - waiting to lock <0x00000000d6f996f0> (a java.lang.String)
        - locked <0x00000000d6f996c0> (a java.lang.String)
        at threaddemo.DeadLockDemo$$Lambda$1/2084435065.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)

jmap

   jmap是一个多功能的命令。它可以生成 java 程序的 dump 文件, 也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列。
例如:打印出堆内存相关信息:

H:\IDEAworkSpace\springdemo>jmap -heap 18904
Attaching to process ID 18904, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.74-b02

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 2071986176 (1976.0MB)
   NewSize                  = 42991616 (41.0MB)
   MaxNewSize               = 690487296 (658.5MB)
   OldSize                  = 87031808 (83.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 32505856 (31.0MB)
   used     = 7808328 (7.446601867675781MB)
   free     = 24697528 (23.55339813232422MB)
   24.02129634734123% used
From Space:
   capacity = 5242880 (5.0MB)
   used     = 0 (0.0MB)
   free     = 5242880 (5.0MB)
   0.0% used
To Space:
   capacity = 5242880 (5.0MB)
   used     = 0 (0.0MB)
   free     = 5242880 (5.0MB)
   0.0% used
PS Old Generation
   capacity = 87031808 (83.0MB)
   used     = 0 (0.0MB)
   free     = 87031808 (83.0MB)
   0.0% used

3514 interned Strings occupying 286552 bytes.

dump出堆内存相关信息:

H:\IDEAworkSpace\springdemo>jmap -dump:format=b,file=G://heap.hprof 18904
Dumping heap to G:\heap.hprof ...
Heap dump file created

一般在开发中,JVM参数可以加上下面两句,这样内存溢出时,会自动dump出该文件
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof

常用的分析工具

jconsole

   JConsole工具是JDK自带的可视化监控工具。查看java应用程序的运行概况、监控堆信息、永久区使用
情况、类加载情况等,直接输入命令jconsole即可打开:
如图所示:

1181802-20200105170932906-1813847637.png
JConsole 基本包括以下基本功能:概述、内存、线程、类、VM概要、MBean。并且可以对线程进行死锁检测。

jvisualvm

   它主要用来监控JVM的运行情况,可以用它来查看和浏览Heap Dump、Thread Dump、内存对象实例情况、GC执行情况、CPU消耗以及类的装载情况。
使用jvisualvm来监控需要安装插件:VisualVM,可以直接访问官网:https://visualvm.github.io/pluginscenters.html 下载对应的jdk版本安装即可。安装之后打开,选择一个java进程监控,如图:
jvisualvm工具使用起来要更直观一点,界面也很友好。可以看到它给我们检测到一个死锁,
1181802-20200105170941087-1829301856.png

并且可以直接查看线程dump。
1181802-20200105170937257-2095139780.png
并且 也可以直接添加dump文件进行分析。
1181802-20200105170922667-1770959554.png

Arthas

   Arthas 是开源出来的一款 Java 诊断利器。主要是针对线上环境,Arthas采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。
这里我们使用官网推荐的arthas-boot

下载arthas-boot.jar,然后用java -jar的方式启动:

curl -O https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar

如图所示,启动成功:

1181802-20200105170915926-1898805951.png

使用help命令查看具体每个命令的使用,

[arthas@8656]$ help
 NAME         DESCRIPTION
 help         Display Arthas Help
 keymap       Display all the available keymap for the specified connection.
 sc           Search all the classes loaded by JVM
 sm           Search the method of classes loaded by JVM
 classloader  Show classloader info
 jad          Decompile class
 getstatic    Show the static field of a class
 monitor      Monitor method execution statistics, e.g. total/success/failure count, average rt, fail rate, etc.
 stack        Display the stack trace for the specified class and method
 thread       Display thread info, thread stack
 trace        Trace the execution time of specified method invocation.
 watch        Display the input/output parameter, return object, and thrown exception of specified method invocation
 tt           Time Tunnel
 jvm          Display the target JVM information
 ognl         Execute ognl expression.
 mc           Memory compiler, compiles java files into bytecode and class files in memory.
 redefine     Redefine classes. @see Instrumentation#redefineClasses(ClassDefinition...)
 dashboard    Overview of target jvm's thread, memory, gc, vm, tomcat info.
 dump         Dump class byte array from JVM
 heapdump     Heap dump
 options      View and change various Arthas options
 cls          Clear the screen
 reset        Reset all the enhanced classes
 version      Display Arthas version
 shutdown     Shutdown Arthas server and exit the console
 stop         Stop/Shutdown Arthas server and exit the console. Alias for shutdown.
 session      Display current session information
 sysprop      Display, and change the system properties.
 sysenv       Display the system env.
 vmoption     Display, and update the vm diagnostic options.
 logger       Print logger info, and update the logger level
 history      Display command history
 cat          Concatenate and print files
 pwd          Return working directory name
 mbean        Display the mbean information
 grep         grep command for pipes.
 profiler     Async Profiler. https://github.com/jvm-profiling-tools/async-profiler

想要了解更过多Arthas的相关信息可以查看官网:https://github.com/alibaba/arthas

MAT

   MAT(Memory Analyzer Tool)工具是eclipse的一个插件(可以单独使用),使用起来非常方便,尤其是在分析大内存的dump文件时,可以非常直观的看到各个对象在堆空间中所占用的内存大小、类实例数量、对象引用关系、利用OQL对象查询,以及可以很方便的找出对象GC Roots的相关信息,还能够快速为开发人员生成内存泄露报表,方便定位问题和分析问题。
MAT官网下载地址:https://www.eclipse.org/mat/downloads.php
下载好之后,打开工具,我这里找了一个OOM的的dump文件,使用MAT打开这个文件:

首先介绍下这个工具的常用选项:

视图含义
HistogramHistogram可以列出内存中的对象,对象的个数及其大小
Dominator tree占用总内存的百分比来列举所有实例对象,可以在这里直观的看到哪些是大对象
Top Consumers该视图会显示可能的内存泄漏点
Leak Suspects通过MA自动分析泄漏的原因

Histogram

它按类名将所有的实例对象列出来,点击表头(Class Name)可以排序,第一行输入正则表达式可以过滤筛选 ;

1181802-20200108113725718-1645590532.png

  • Class Name : 类名称,java类名
  • Objects : 类的对象的数量,这个对象被创建了多少个
  • Shallow Heap :一个对象内存的消耗大小,不包含对其他对象的引用
  • Retained Heap :是shallow Heap的总和,也就是该对象被GC之后所能回收到内存的总和
    快速找出某个实例没被释放的原因,可以右健 Path to GC Roots–>exclude all phantom/weak/soft etc. references
    它展示了对象间的引用关系:

1181802-20200108113731858-1493183502.png

Dominator tree:

以占用总内存的百分比来列举所有实例对象,可以在这里直观的看到哪些是大对象:

1181802-20200108113737462-1985979925.png

Top Consumers:

这个维度展示了对象占用的内存分布:

1181802-20200108113742215-756763329.png

可以查看每一个列表下面的分析:

1181802-20200108114834975-136106331.png

Leak Suspects:

1181802-20200108115257313-1210102695.png
   界面上非常直观的展示了一个饼图,该图深色区域被怀疑有内存泄漏,可以发现整个heap才15M内存,深色区域就占了92.48%。接下来是一个简短的描述,告诉我们main线程占用了大量内存,并且明确指出system class loader加载的“java.lang.Thread”实例有内存聚集,并建议用关键字“java.lang.Thread”进行检查。在下面还有一个“Details”链接,可以查看明细信息。
   以上只是简单的介绍了下MAT工具的使用,具体或者更详细的使用可以查看官网,这里有很多关于MAT的使用经验及介绍。https://wiki.eclipse.org/MemoryAnalyzer/Learning_Material

   本篇文章罗列了一些JVM内存相关的参数和一些获取JVM运行状况的一些参数以及线程Dump,堆Dump等分析工具,理解这些参数命令和熟悉工具的使用是我们读懂GC日志和对JVM进行调优的前提。


版权声明:本文为jiuchengyixi原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。