JDK性能调优命令

1、环境

一个可运行的java程序。本例选择的是xboot (一个基于springboot 开发的后台管理框架)附上地址。jdk版本:1.8
https://github.com/Exrick/xboot

2、命令

2.1 Jinfo

先用jps 命令查看应用的进程
C:\Users\lujw0>jps
1128 XbootApplication
14924 Jps
通过jps命令可以查出xboot 项目的进程id是1128。

- 查看正在运行的Java应用程序的扩展参数
C:\Users\lujw0>jinfo -flags 1128
Attaching to process ID 1128, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.102-b14
Non-default VM flags: -XX:-BytecodeVerificationLocal -XX:-BytecodeVerificationRemote -XX:CICompilerCount=3 -XX:InitialHeapSize=134217728 -XX:+ManagementServer -XX:MaxHeapSize=2120220672 -XX:MaxNewSize=706740224 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=44564480 -XX:OldSize=89653248 -XX:TieredStopAtLevel=1 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:4099,suspend=y,server=n -XX:TieredStopAtLevel=1 -Xverify:none -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -javaagent:C:\Users\lujw0\.IntelliJIdea2019.1\system\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8
上边的这些参数下面会讲,都是对jvm调优配置的一些参数。

- 查看java 系统参数
C:\Users\lujw0>jinfo -sysprops 1128
Attaching to process ID 1128, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.102-b14
spring.output.ansi.enabled = always
java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.102-b14
sun.boot.library.path = C:\Program Files\Java\jdk1.8.0_102\jre\bin
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = ;
java.rmi.server.randomIDs = true
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
sun.os.patch.level =
sun.java.launcher = SUN_STANDARD
user.script =
user.country = CN
user.dir = F:\bdyhwork\wenda_bms
java.vm.specification.name = Java Virtual Machine Specification
PID = 1128
intellij.debug.agent = true
java.runtime.version = 1.8.0_102-b14
java.awt.graphicsenv = sun.awt.Win32GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = C:\Program Files\Java\jdk1.8.0_102\jre\lib\endorsed
line.separator =

java.io.tmpdir = C:\Users\lujw0\AppData\Local\Temp\
java.vm.specification.vendor = Oracle Corporation
user.variant =
os.name = Windows 10
sun.jnu.encoding = GBK
java.library.path = C:\Program Files\Java\jdk1.8.0_102\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files (x86)\NetSarang\Xshell 6\;C:\Program Files (x86)\NetSarang\Xftp 6\;E:\soft\node\nodeinstall\;C:\windows\system32\;C:\Program Files\TortoiseGit\bin;C:\Program Files\Git\cmd;C:\Users\lujw0\AppData\Local\Android\sdk\platform-tools;C:\Users\lujw0\AppData\Local\Microsoft\WindowsApps;E:\soft\idea 2019\IntelliJ IDEA 2019.1\plugins\maven\lib\maven3\bin;E:\soft\Git\bin;E:\soft\Git\mingw32\libexec\git-core;C:\Users\lujw0\AppData\Roaming\npm;E:\soft\webstom\WebStorm 2019.2.1\bin;C:\Program Files\Java\jdk1.8.0_102\bin;C:\Program Files\Java\jdk1.8.0_102\jre\bin;.
spring.beaninfo.ignore = true
jboss.modules.system.pkgs = com.intellij.rt
java.class.version = 52.0
java.specification.name = Java Platform API Specification
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
spring.liveBeansView.mbeanDomain =
os.version = 10.0
user.home = C:\Users\lujw0
user.timezone = Asia/Shanghai
catalina.useNaming = false
java.awt.printerjob = sun.awt.windows.WPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
catalina.home = C:\Users\lujw0\AppData\Local\Temp\tomcat.5173769956863843077.8888
user.name = bdzh01
java.class.path = C:\Users\lujw0\AppData\Local\Temp\classpath1301191800.jar;C:\Users\lujw0\.IntelliJIdea2019.1\system\captureAgent\debugger-agent.jar
com.sun.management.jmxremote =
java.vm.specification.version = 1.8
sun.arch.data.model = 64
sun.java.command = cn.exrick.xboot.XbootApplication
java.home = C:\Program Files\Java\jdk1.8.0_102\jre
user.language = zh
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.windows.WToolkit
java.vm.info = mixed mode
java.version = 1.8.0_102
java.ext.dirs = C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
sun.boot.class.path = C:\Program Files\Java\jdk1.8.0_102\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_102\jre\classes
java.awt.headless = true
java.vendor = Oracle Corporation
catalina.base = C:\Users\lujw0\AppData\Local\Temp\tomcat.5173769956863843077.8888
spring.application.admin.enabled = true
file.separator = \
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
sun.desktop = windows
sun.cpu.isalist = amd64

jinfo -sysprops 这个命令会更加详细会打印出项目运行的环境信息。

2.2 jstat

jstat:该命令可以插件堆内存各部分的使用量,以及加载类的数量。命令格式如下 jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]

- 类加载统计
C:\Users\lujw0>jstat -class 1128
Loaded  Bytes    Unloaded       Bytes       Time
 16315 30104.4        0           0.0       37.11

Loaded:加载class的数量
Bytes:所占用空间大小
Unloaded:未加载数量
Bytes:未加载占用空间
Time:时间

-垃圾回收统计
C:\Users\lujw0>jstat -gc 1128
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
5632.0 28160.0 5328.0  0.0   525824.0 463666.6  138752.0   96939.8   86912.0 82755.8 11648.0 10941.9     28    0.367   3      0.571    0.938
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小(元空间)
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

-堆内存统计
C:\Users\lujw0>jstat -gccapacity 1128
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC
 43520.0 690176.0 583168.0 25600.0 5632.0 461312.0    87552.0  1380352.0   138752.0   138752.0      0.0 1124352.0  87168.0      0.0 1048576.0  11648.0     31     3
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0C:第一个幸存区大小
S1C:第二个幸存区的大小
EC:伊甸园区的大小
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:当前老年代大小
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代gc次数
FGC:老年代GC次数

-新生代垃圾回收统计
C:\Users\lujw0>jstat -gcnew 1128
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
25600.0 5632.0    0.0 5152.0  9  15 25600.0 461312.0 257085.0     31    0.401
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
TT:对象在新生代存活的次数
MTT:对象在新生代存活的最大次数
DSS:期望的幸存区大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间

-新生代内存统计
C:\Users\lujw0>jstat -gcnewcapacity 1128
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC
   43520.0   690176.0   583168.0 229888.0  25600.0 229888.0   5632.0   689152.0   461312.0    31     3
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0CMX:最大幸存1区大小
S0C:当前幸存1区大小
S1CMX:最大幸存2区大小
S1C:当前幸存2区大小
ECMX:最大伊甸园区大小
EC:当前伊甸园区大小
YGC:年轻代垃圾回收次数
FGC:老年代回收次数

-老年代垃圾回收统计
C:\Users\lujw0>jstat -gcold 1128
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT
 87168.0  82884.4  11648.0  10941.9    138752.0     96971.8     32     3    0.571    0.983
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
OC:老年代大小
OU:老年代使用大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

-老年代内存统计
C:\Users\lujw0>jstat -gcoldcapacity 1128
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT
    87552.0   1380352.0    138752.0    138752.0    32     3    0.571    0.983
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:老年代大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

-元数据空间统计
C:\Users\lujw0>jstat -gcmetacapacity 1128
   MCMN       MCMX        MC       CCSMN      CCSMX       CCSC     YGC   FGC    FGCT     GCT
       0.0  1124352.0    87168.0        0.0  1048576.0    11648.0    32     3    0.571    0.983
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

-总结垃圾回收统计
C:\Users\lujw0>jstat -gcutil 1128
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
 91.76   0.00  95.12  69.89  95.09  93.94     32    0.412     3    0.571    0.983
S0:幸存1区当前使用比例
S1:幸存2区当前使用比例
E:伊甸园区使用比例
O:老年代使用比例
M:元数据区使用比例
CCS:压缩使用比例
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

2.3、Jmap(常用)

此命令可以产看内存信息

-实例个数以及占有内存大小
C:\Users\lujw0>jmap -histo 1128 >./hmaplog.txt
 num     #instances         #bytes  class name
----------------------------------------------
   1:       1246051      216721832  [C
   2:        800697       19216728  java.lang.String
   3:         19592       12175032  [B
   4:        183451        7338040  java.util.LinkedHashMap$Entry
   5:         78428        6901664  java.lang.reflect.Method
   6:         13787        5713720  [I
   7:        201053        4825272  java.util.LinkedList$Node
   8:        190438        4570512  com.intellij.rt.debugger.agent.CaptureStorage$HardKey
   9:        105248        4209920  org.springframework.boot.devtools.filewatch.FileSnapshot
  10:        129555        4145760  java.io.File
  11:         36369        4074608  [Ljava.util.HashMap$Node;
  12:         80872        3844216  [Ljava.lang.String;
  13:        119361        3819552  java.util.concurrent.ConcurrentHashMap$Node
  14:        107645        3444640  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
  15:         53509        2703504  [Ljava.lang.Object;
  16:         80417        2573344  java.util.HashMap$Node
  17:         35803        2004968  java.util.LinkedHashMap
  18:         17368        1933400  java.lang.Class
  19:         51969        1663008  java.lang.ref.WeakReference
  20:          1122        1466832  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  21:         52470        1259280  java.util.ArrayList
  22:         57148        1256584  [Ljava.lang.Class;
  23:         15724        1132128  java.lang.reflect.Field
num:序号
instances:实例数量
bytes:占用空间大小
class name:类名称

-堆信息
C:\Users\lujw0>jmap -heap 1128
Attaching to process ID 1128, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.102-b14

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

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 2120220672 (2022.0MB)
   NewSize                  = 44564480 (42.5MB)
   MaxNewSize               = 706740224 (674.0MB)
   OldSize                  = 89653248 (85.5MB)
   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 = 415760384 (396.5MB)
   used     = 364749400 (347.85213470458984MB)
   free     = 51010984 (48.647865295410156MB)
   87.73067710077927% used
From Space:
   capacity = 5242880 (5.0MB)
   used     = 5046320 (4.8125457763671875MB)
   free     = 196560 (0.1874542236328125MB)
   96.25091552734375% used
To Space:
   capacity = 23068672 (22.0MB)
   used     = 0 (0.0MB)
   free     = 23068672 (22.0MB)
   0.0% used
PS Old Generation
   capacity = 142082048 (135.5MB)
   used     = 99299144 (94.69904327392578MB)
   free     = 42782904 (40.80095672607422MB)
   69.88859282208544% used

42219 interned Strings occupying 4803176 bytes.

-堆内存的dump 文件
C:\Users\lujw0>jmap -dump:format=b,file=xbootdump.hprof 1128
Dumping heap to C:\Users\lujw0\xbootdump.hprof ...
Heap dump file created
也可以设置内存溢出自动导出dump文件(内存很大的时候,可能会导不出来)
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./   (路径)

可以用jvisualvm命令工具导入该dump文件分析
C:\Users\lujw0>jvisualvm
输入上述命令之后就会打开jdk 自带的内存分析工具jvisualvm

image.png

image.png

2.4、Jstack

jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",
Windows的jstack使用方式只支持以下的这种方式:jstack [-l] pid
如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

C:\Users\lujw0>jstack 1128
2020-02-22 12:16:36
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.102-b14 mixed mode):

"RMI TCP Connection(6)-192.168.5.83" #203 daemon prio=5 os_prio=0 tid=0x00000000211cc000 nid=0x38d0 runnable [0x000000002b66d000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:170)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
        - locked <0x00000000ee61a020> (a java.io.BufferedInputStream)
        at java.io.FilterInputStream.read(FilterInputStream.java:83)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:550)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$1/1653161508.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

"JMX server connection timeout 202" #202 daemon prio=5 os_prio=0 tid=0x00000000211c4800 nid=0x3a30 in Object.wait() [0x000000002b36f000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
        - locked <0x00000000ee610a10> (a [I)
        at java.lang.Thread.run(Thread.java:745)

用jstack查找死锁,见如下示例,也可以用jvisualvm查看死锁
新写一个java 死锁的程序
public class DeadLockTest {
    public static Object lock1 = new Object();
    public static Object lock2 = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (lock1) {
                try {
                    System.out.println("thread1 开始执行");
                    Thread.sleep(500);
                } catch (Exception e) {
                }
                synchronized (lock2) {
                    System.out.println("thread1 执行结束");
                }
            }
        }).start();
        new Thread(() -> {
            synchronized (lock2) {
                try {
                    System.out.println("thread2 开始执行");
                    Thread.sleep(500);
                } catch (Exception e) {
                }
                synchronized (lock1) {
                    System.out.println("thread2 执行结束");
                }
            }
        }).start();
    }
}

通过jstack +进程id 也可以查看

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00000000181305a8 (object 0x00000000d6157ef0, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x000000001812dc68 (object 0x00000000d6157f00, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at com.spring.study.user.test.DeadLockTest.lambda$main$1(DeadLockTest.java:33)
        - waiting to lock <0x00000000d6157ef0> (a java.lang.Object)
        - locked <0x00000000d6157f00> (a java.lang.Object)
        at com.spring.study.user.test.DeadLockTest$$Lambda$2/1792845110.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)
"Thread-0":
        at com.spring.study.user.test.DeadLockTest.lambda$main$0(DeadLockTest.java:21)
        - waiting to lock <0x00000000d6157f00> (a java.lang.Object)
        - locked <0x00000000d6157ef0> (a java.lang.Object)
        at com.spring.study.user.test.DeadLockTest$$Lambda$1/716143810.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

通过jvisualvm 查看死锁


image.png

远程连接jvisualvm

启动普通的jar程序JMX端口配置:
java -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar foo.jar

tomcat的JMX配置
JAVA_OPTS=-Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false

jvisualvm远程连接服务需要在远程服务器上配置host(连接ip 主机名),并且要关闭防火墙

image.png

jstack找出占用cpu最高的堆栈信息

1,使用命令top -p <pid> ,显示你的java进程的内存情况,pid是你的java进程号,比如4977
2,按H,获取每个线程的内存情况
3,找到内存和cpu占用最高的线程tid,比如4977
4,转为十六进制得到 0x1371 ,此为线程id的十六进制表示
5,执行 jstack 4977|grep -A 10 1371,得到线程堆栈信息中1371这个线程所在行的后面10行
6,查看对应的堆栈信息找出可能存在问题的代码

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容