jmap

常用来查看jvm的内存信息,比如对象的实例个数以及对象占用的内存大小。

示例代码

public class JmapCode {

    public static void main(String[] args) throws InterruptedException {
        List<User> users = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            users.add(new User());
        }
        Thread.sleep(Long.MAX_VALUE);
    }

    private static class User {}
}

jps查看系统内java进程

➜  ~ jps
62304 Jps
59988
62278 JmapCode

jmap -histo <进程id> (查看jvm中对象的内存信息)

➜  ~ jmap -histo 62278
num     #instances         #bytes  class name
----------------------------------------------
   1:           984        2823608  [I
   2:          1755        1430760  [B
   3:          5566         674256  [C
   4:          3673          88152  java.lang.String
   5:           654          74776  java.lang.Class
   6:           766          56176  [Ljava.lang.Object;
   7:          1000          16000  com.heoller.JmapCode$User
...(省略)

jmap -heap <进程id> (查看jvm内存信息)

Attaching to process ID 80244, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 10.0.1+10

using thread-local object allocation.
Garbage-First (G1) GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 4294967296 (4096.0MB)
   NewSize                  = 1363144 (1.2999954223632812MB)
   MaxNewSize               = 2576351232 (2457.0MB)
   OldSize                  = 5452592 (5.1999969482421875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 1048576 (1.0MB)

Heap Usage:
G1 Heap:
   regions  = 4096
   capacity = 4294967296 (4096.0MB)
   used     = 1048576 (1.0MB)
   free     = 4293918720 (4095.0MB)
   0.0244140625% used
G1 Young Generation:
Eden Space:
   regions  = 1
   capacity = 15728640 (15.0MB)
   used     = 1048576 (1.0MB)
   free     = 14680064 (14.0MB)
   6.666666666666667% used
Survivor Space:
   regions  = 0
   capacity = 0 (0.0MB)
   used     = 0 (0.0MB)
   free     = 0 (0.0MB)
   0.0% used
G1 Old Generation:
   regions  = 0
   capacity = 252706816 (241.0MB)
   used     = 0 (0.0MB)
   free     = 252706816 (241.0MB)
   0.0% used

2036 interned Strings occupying 146048 bytes.

jmap -dump:format=b,file=jampCode.hprof <进程id> (生成dump文件,可以导进jvisualvm工具中查看)

heap

通常是通过设置jvm启动参数来获取内存溢出时堆内存的dump文件
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./oom.dump

public class OOMCode {
    /**
     * -Xms1M -Xmx1M -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./oom.dump
     * @param args
     */
    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        for (;;) {
            users.add(new User());
        }
    }

    private static class User {}
}
# 运行结果
java.lang.OutOfMemoryError: Java heap space
Dumping heap to ./oom.dump ...
Heap dump file created [2328675 bytes in 0.024 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3210)
    at java.util.Arrays.copyOf(Arrays.java:3181)
    at java.util.ArrayList.grow(ArrayList.java:265)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
    at java.util.ArrayList.add(ArrayList.java:462)
    at com.heoller.OOMCode.main(OOMCode.java:19)

oom

jstack

示例代码

public class DeadLockCode {

    private static Object resourceA = new Object();
    private static Object resourceB = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (resourceA) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (resourceB) {
                    System.out.println();
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (resourceB) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (resourceA) {
                    System.out.println();
                }
            }
        }).start();
    }
}

jstack <进程id> (检测出来死锁)

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00007fd78b811958 (object 0x000000076aeb55e8, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x00007fd78b80ee08 (object 0x000000076aeb55f8, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
    at com.heoller.DeadLockCode.lambda$main$1(DeadLockCode.java:36)
    - waiting to lock <0x000000076aeb55e8> (a java.lang.Object)
    - locked <0x000000076aeb55f8> (a java.lang.Object)
    at com.heoller.DeadLockCode$$Lambda$2/127618319.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)
"Thread-0":
    at com.heoller.DeadLockCode.lambda$main$0(DeadLockCode.java:22)
    - waiting to lock <0x000000076aeb55f8> (a java.lang.Object)
    - locked <0x000000076aeb55e8> (a java.lang.Object)
    at com.heoller.DeadLockCode$$Lambda$1/940553268.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

同时jvisualvm也可以检测到死锁
jvisualvm

jstack <pid> (查看CPU高的线程堆栈信息)</pid>

示例代码
public class CPUCode {
    public static void main(String[] args) {
        for(;;){}
    }
}
  • 定位java进程
[heoller@localhost ~]$ jps
4050 CPUCode
4090 Jps
  • top -p 4050 后键入H,找到CPU最高的线程id,并换算成16进制
[heoller@localhost ~]$ top -p 4050
top - 23:19:58 up 6 min,  3 users,  load average: 0.89, 0.62, 0.31
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s): 10.4 us,  2.3 sy,  0.0 ni, 84.4 id,  2.8 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1868688 total,   859704 free,   511500 used,   497484 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  1162248 avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  4050 heoller   20   0 2888108  22968  10228 S 100.0  1.2   0:38.49 java
------------------键入H后,发现4051占用cpu最高------------------------
top - 23:20:05 up 6 min,  3 users,  load average: 0.91, 0.63, 0.31
Threads:  15 total,   1 running,  14 sleeping,   0 stopped,   0 zombie
%Cpu(s): 24.7 us,  0.0 sy,  0.0 ni, 75.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1868688 total,   858928 free,   512376 used,   497384 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  1161504 avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
  4051 heoller   20   0 2888108  22968  10228 R 99.7  1.2   0:46.34 java
  4064 heoller   20   0 2888108  22968  10228 S  0.3  1.2   0:00.03 java
  4050 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4052 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4053 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4054 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4055 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4056 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4057 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4058 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4059 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4060 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4061 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4062 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  4063 heoller   20   0 2888108  22968  10228 S  0.0  1.2   0:00.00 java
  • jstack 4050|grep -A 5 <16进制数(字母小写)>
[heoller@localhost ~]$ jstack 4050|grep -A 5 fd3
"main" #1 prio=5 os_prio=0 tid=0x00007f200c009800 nid=0xfd3 runnable [0x00007f2013edf000]
   java.lang.Thread.State: RUNNABLE
        at CPUCode.main(CPUCode.java:3)

"VM Thread" os_prio=0 tid=0x00007f200c078000 nid=0xfd8 runnable

jinfo

查看JVM启动参数

➜  ~ jinfo -flags 4251

查看Java系统参数

➜  ~ jinfo -sysprops 4954

jstat

动态查看堆内存大小的变化以及gc情况

➜  ~ jstat -gc 6508 1000 3
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC     FGCT     GCT(GC总耗时)
512.0  512.0  496.0   0.0    512.0    482.9     512.0       65.1    4864.0 3294.3 512.0  369.4       4    0.016   0      0.000    0.016
512.0  512.0  496.0   0.0    512.0    482.9     512.0       65.1    4864.0 3294.3 512.0  369.4       4    0.016   0      0.000    0.016
512.0  512.0  496.0   0.0    512.0    482.9     512.0       65.1    4864.0 3294.3 512.0  369.4       4    0.016   0      0.000    0.016