深入JVM内核10 JDK调优命令

jps 用来查看JVM里面所有进程的具体状态, 包括进程ID,进程启动的路径等等。

jinfo–可以知道崩溃的JVM参数配置信息及JDK版本安装路径等信息。

jstat– JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控等等。

jmap+jhat–jmap可以生成堆转储快照文件,jhat可以查看快照文件分析内存溢出可能的原因。

jstack-- 获取JVM当前线程,JVM内每个线程正在执行方法的栈信息,包括线程状态,什么线程操作导致当前线程状态。

jdb– jdb 用来对core文件和正在运行的Java进程进行实时地调试,里面包含了丰富的命令帮助您进行调试,它的功能和Sun studio里面所带的dbx非常相似,但 jdb是专门用来针对Java应用程序的。

jconsole– jconsole是基于Java Management Extensions (JMX)的实时图形化监测工具,这个工具利用了内建到JVM里面的JMX指令来提供实时的性能和资源的监控,包括了Java程序的内存使用,Heap size, 线程的状态,类的分配状态和空间使用等等。

1.jps

实际中这是最常用的命令,下面要介绍的小工具更多的都是先要使用jps查看出当前有哪些Java进程,获取该Java进程的id后再对该进程进行处理。

jps主要用来输出JVM中运行的进程状态信息。

语法格式如下:

jps [options] [hostid]

如果不指定hostid就默认为当前主机或服务器。

参数解释:
-q 不输出类名、Jar名和传入main方法的参数  
-m 输出传入main方法的参数  
-l 输出main类或Jar的全限名  
-v 输出传入JVM的参数  

C:\Users\kpion>JPS
18704
23360 Jps
13496 Launcher
17324 DemoApplication
5756 JConsole
7196 Main
2.jstat

JVM统计监测工具

jstat可以实时显示本地或远程JVM进程中类装载、内存、垃圾收集、JIT编译等数据(如果要显示远程JVM信息,需要远程主机开启RMI支持)。

如果在服务启动时没有指定启动参数-verbose:gc,则可以用jstat实时查看gc情况。

命令格式:jstat [option vmid [interval[s|ms] [count]]]

参数解释:

Options — 选项,我们一般使用 -gcutil 查看gc情况
vmid    — VM的进程号,即当前运行的java进程号
interval– 间隔时间,单位为秒或者毫秒
count   — 打印次数,如果缺省则打印无数次

-class:
监视类装载、卸载数量、总空间及类装载所耗费的时间
-gc:
监听Java堆状况,包括Eden区、两个Survivor区、老年代、永久代等的容量,以用空间、GC时间合计等信息
-gccapacity:
监视内容与-gc基本相同,但输出主要关注java堆各个区域使用到的最大和最小空间
-gcutil:
监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比如S0为86.53,代表着S0区已使用了86.53%
-gccause:
与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因
-gcnew:
监视新生代GC状况
-gcnewcapacity:
监视内同与-gcnew基本相同,输出主要关注使用到的最大和最小空间
-gcold:
监视老年代GC情况
-gcoldcapacity:
监视内同与-gcold基本相同,输出主要关注使用到的最大和最小空间
-gcpermcapacity:
输出永久代使用到最大和最小空间
-compiler:
输出JIT编译器编译过的方法、耗时等信息
-printcompilation:
输出已经被JIT编译的方法

一些术语的中文解释:
S0C:S0区容量(S1区相同,略)
S0U:S0区已使用
EC:E区容量
EU:E区已使用
OC:老年代容量
OU:老年代已使用
PC:Perm容量
PU:Perm区已使用
YGC:Young GC(Minor GC)次数
YGCT:Young GC总耗时
FGC:Full GC次数
FGCT:Full GC总耗时
GCT:GC总耗时

C:\Users\kpion>jstat -gc 17324
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
17920.0 17920.0  0.0   11704.0 161280.0 119852.1  247296.0   31790.9   74968.0 72899.0 6912.0 6416.6      9    0.081   3      0.192    0.273

C:\Users\kpion>jstat -gc 17324 5
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
17920.0 17920.0  0.0   11704.0 161280.0 139274.2  247296.0   31790.9   74968.0 72899.0 6912.0 6416.6      9    0.081   3      0.192    0.273
17920.0 17920.0  0.0   11704.0 161280.0 139274.2  247296.0   31790.9   74968.0 72899.0 6912.0 6416.6      9    0.081   3      0.192    0.273
17920.0 17920.0  0.0   11704.0 161280.0 139274.2  247296.0   31790.9   74968.0 72899.0 6912.0 6416.6      9    0.081   3      0.192    0.273
17920.0 17920.0  0.0   11704.0 161280.0 139274.2  247296.0   31790.9   74968.0 72899.0 6912.0 6416.6      9    0.081   3      0.192    0.273
17920.0 17920.0  0.0   11704.0 161280.0 139274.2  247296.0   31790.9   74968.0 72899.0 6912.0 6416.6      9    0.081   3      0.192    0.273
省略...

C:\Users\kpion>jstat -gcutil 17324
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
 91.55   0.00  19.07  12.87  97.16  93.92     12    0.183     3    0.192    0.375

3.jstack

jstack能得到运行java程序的java stack和native stack的信息。可以轻松得知当前线程的运行情况。

Usage:
    jstack [-l] 
        (to connect to running process) 连接活动线程
    jstack -F [-m] [-l] 
        (to connect to a hung process) 连接阻塞线程
    jstack [-m] [-l]  
        (to connect to a core file) 连接dump的文件
    jstack [-m] [-l] [server_id@]
        (to connect to a remote debug server) 连接远程服务器

Options:
    -F  to force a thread dump. Use when jstack  does not respond (process is hung)
    -m  to print both java and native frames (mixed mode)
    -l  long listing. Prints additional information about locks
    -h or -help to print this help message
结合top和jstack找出占用cpu最高的堆栈信息

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

[root@iZ2ze4v2sdd3vdp1ne5smhZ ~]# jps
10736 QuorumPeerMain
10768 QuorumPeerMain
11058 QuorumPeerMain
22402 Bootstrap
21596 Jps
[root@iZ2ze4v2sdd3vdp1ne5smhZ ~]# top -p 11058
image.png

我选了11072这个pid,转16进制为2b40

image.png
在thread dump中,要留意下面几种状态
1. 死锁,Deadlock(重点关注)
2. 执行中,Runnable
3. 等待资源,Waiting on condition(重点关注)
4. 等待获取监视器,Waiting on monitor entry(重点关注)
5. 暂停,Suspended
6. 对象等待中,Object.wait() 或 TIMED_WAITING
7. 阻塞,Blocked(重点关注)
  1. 停止,Parked
jstack -l 17324
2020-02-22 12:07:11
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.231-b11 mixed mode):

"RMI TCP Connection(11)-192.168.0.105" #65 daemon prio=5 os_prio=0 tid=0x0000000020f7c000 nid=0x38b8 runnable [0x000000000079d000]
   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:178)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:249)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
        - locked <0x000000076e791618> (a java.io.BufferedInputStream)
        at java.io.FilterInputStream.read(FilterInputStream.java:83)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:857)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$390/1850215416.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:692)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
        - <0x000000076e70bb18> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"RMI TCP Connection(9)-192.168.0.105" #63 daemon prio=5 os_prio=0 tid=0x0000000020f77800 nid=0x27ac in Object.wait() [0x0000000026bbc000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at com.sun.jmx.remote.internal.ArrayNotificationBuffer.fetchNotifications(ArrayNotificationBuffer.java:481)
        - locked <0x00000007790080a0> (a com.sun.jmx.remote.internal.ArrayNotificationBuffer)
        at com.sun.jmx.remote.internal.ArrayNotificationBuffer$ShareBuffer.fetchNotifications(ArrayNotificationBuffer.java:227)
        at com.sun.jmx.remote.internal.ServerNotifForwarder.fetchNotifs(ServerNotifForwarder.java:277)
        at javax.management.remote.rmi.RMIConnectionImpl$4.run(RMIConnectionImpl.java:1270)
        at javax.management.remote.rmi.RMIConnectionImpl$4.run(RMIConnectionImpl.java:1268)
        at javax.management.remote.rmi.RMIConnectionImpl.fetchNotifications(RMIConnectionImpl.java:1276)
        at sun.reflect.GeneratedMethodAccessor123.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:367)
        at sun.rmi.transport.Transport$1.run(Transport.java:200)
        at sun.rmi.transport.Transport$1.run(Transport.java:197)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.Transport.serviceCall(Transport.java:210)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:580)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:857)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$390/1850215416.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:692)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
        - <0x0000000779010800> (a java.util.concurrent.ThreadPoolExecutor$Worker)
jstack检测死锁
死锁代码
public class DeadLock {
    public static void main(String[] args) {
        System.out.println(" start the example ----- ");
        final Object obj_1 = new Object(), obj_2 = new Object();

        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                synchronized (obj_1) {
                    try {
                        System.out.println("thread t1 start...");
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {e.printStackTrace();}

                    synchronized (obj_2) {
                        System.out.println("thread t1 done....");
                    }
                }
            }
        };

        Thread t2 = new Thread("t2") {
            @Override
            public void run() {
                synchronized (obj_2) {
                    try {
                        System.out.println("thread t2 start...");
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {e.printStackTrace();}

                    synchronized (obj_1) {
                        System.out.println("thread t2 done...");
                    }
                }
            }
        };

        t1.start();
        t2.start();
    }

}
C:\Users\kpion>jps
13488 Jps
13984 DeadLock
18704
21464 Launcher
17324 DemoApplication
5756 JConsole
7196 Main

C:\Users\kpion> jstack -l 13984
...省略
Found one Java-level deadlock:
=============================
"t2":
  waiting to lock monitor 0x000000001c5b3608 (object 0x000000076b77dcb8, a java.lang.Object),
  which is held by "t1"
"t1":
  waiting to lock monitor 0x000000001c5b0d78 (object 0x000000076b77dcc8, a java.lang.Object),
  which is held by "t2"

Java stack information for the threads listed above:
===================================================
"t2":
        at com.kpioneer.demo.DeadLock$2.run(DeadLock.java:39)
        - waiting to lock <0x000000076b77dcb8> (a java.lang.Object)
        - locked <0x000000076b77dcc8> (a java.lang.Object)
"t1":
        at com.kpioneer.demo.DeadLock$1.run(DeadLock.java:23)
        - waiting to lock <0x000000076b77dcc8> (a java.lang.Object)
        - locked <0x000000076b77dcb8> (a java.lang.Object)

Found 1 deadlock.
继续使用jstack来分析HashMap在多线程情况下的死锁问题:
   对于如下代码,使用10个线程来处理提交的2000个任务,每个任务会分别循环往hashmap中分别存入和取出1000个数,通过测试发现,程序并不能完整执行完成
2020-02-22 14:33:18
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.231-b11 mixed mode):

"DestroyJavaVM" #22 prio=5 os_prio=0 tid=0x000000001f82f800 nid=0x1d00 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"pool-1-thread-10" #21 prio=5 os_prio=0 tid=0x000000001f7e7800 nid=0x2edc waiting on condition [0x000000002097f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
    at java.lang.Thread.sleep(Native Method)
    at com.kpioneer.demo.HashMapDeadLock.call(HashMapDeadLock.java:31)
    at com.kpioneer.demo.HashMapDeadLock.call(HashMapDeadLock.java:15)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
    - <0x000000076f5007a0> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"pool-1-thread-9" #20 prio=5 os_prio=0 tid=0x000000001f7e7000 nid=0x4a80 waiting on condition [0x000000002087f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
    at java.lang.Thread.sleep(Native Method)
    at com.kpioneer.demo.HashMapDeadLock.call(HashMapDeadLock.java:31)
    at com.kpioneer.demo.HashMapDeadLock.call(HashMapDeadLock.java:15)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
    - <0x000000076f508c30> (a java.util.concurrent.ThreadPoolExecutor$Worker)
死循环
public class EndlessLoop {
    public static void main(String[] args) throws InterruptedException {
        while (true) {

        }
    }
}
C:\Users\kpion>jps
13984 DeadLock
17136 Launcher
18704
18100 EndlessLoop
23460 Jps
17324 DemoApplication
5756 JConsole
7196 Main

C:\Users\kpion>jstack -l 18100 > endless.jstack
2020-02-22 15:31:42
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.231-b11 mixed mode):

"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x000000001eb6b800 nid=0x3514 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"C1 CompilerThread3" #10 daemon prio=9 os_prio=2 tid=0x000000001eac8000 nid=0x1680 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"C2 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x000000001eac3000 nid=0x1d50 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001eabf800 nid=0x4e24 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x000000001eabc800 nid=0x4f88 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001ea9d800 nid=0x4a34 runnable [0x000000001f12e000]
   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:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    - locked <0x000000076b84a2a8> (a java.io.InputStreamReader)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    - locked <0x000000076b84a2a8> (a java.io.InputStreamReader)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

   Locked ownable synchronizers:
    - None

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001e8c1000 nid=0x2460 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001e86a000 nid=0x2fd4 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001e851800 nid=0x3790 in Object.wait() [0x000000001ee2e000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000076b588ed8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
    - locked <0x000000076b588ed8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

   Locked ownable synchronizers:
    - None

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001e850800 nid=0x587c in Object.wait() [0x000000001ed2e000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000076b586c00> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:502)
    at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
    - locked <0x000000076b586c00> (a java.lang.ref.Reference$Lock)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

   Locked ownable synchronizers:
    - None

"main" #1 prio=5 os_prio=0 tid=0x0000000002f74800 nid=0x178c runnable [0x0000000002daf000]
   java.lang.Thread.State: RUNNABLE
    at com.kpioneer.demo.EndlessLoop.main(EndlessLoop.java:10)

   Locked ownable synchronizers:
    - None

"VM Thread" os_prio=2 tid=0x000000001ca59800 nid=0x57cc runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002f8a800 nid=0x628 runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002f8c000 nid=0x45f4 runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002f8d800 nid=0x5aec runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002f8f000 nid=0x37cc runnable 

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x0000000002f91800 nid=0x43e0 runnable 

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000002f93800 nid=0x4704 runnable 

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000002f97000 nid=0x2cf0 runnable 

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000002f98000 nid=0x3b3c runnable 

"VM Periodic Task Thread" os_prio=2 tid=0x000000001ebe9800 nid=0x4aa0 waiting on condition 

JNI global references: 12
Object.wait()情况
class TestTask implements Runnable {
    @Override
    public void run() {

        synchronized (this) {
            try {
                //等待被唤醒
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

public class WaitTest {

    public static void main(String[] args) throws InterruptedException {

        ExecutorService ex = Executors.newFixedThreadPool(1);
        ex.execute(new TestTask());

    }
}
C:\Users\kpion>jps
13984 DeadLock
18704
24448 Launcher
8992 WaitTest
1076 Jps
18100 EndlessLoop
17324 DemoApplication
5756 JConsole
7196 Main

C:\Users\kpion>jstack -l 8992 > wait.jstack
2020-02-22 15:40:48
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.231-b11 mixed mode):

"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x00000000034c4800 nid=0x3904 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"pool-1-thread-1" #12 prio=5 os_prio=0 tid=0x000000001fd03000 nid=0x1924 in Object.wait() [0x000000002059f000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000076b792658> (a com.kpioneer.demo.TestTask)
    at java.lang.Object.wait(Object.java:502)
    at com.kpioneer.demo.TestTask.run(WaitTest.java:19)
    - locked <0x000000076b792658> (a com.kpioneer.demo.TestTask)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
    - <0x000000076b7931b0> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x000000001f0e1000 nid=0x3018 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"C1 CompilerThread3" #10 daemon prio=9 os_prio=2 tid=0x000000001f039800 nid=0x480 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"C2 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x000000001f034800 nid=0x5cbc waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001f031000 nid=0x3c0c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x000000001f02c000 nid=0x1010 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001efda000 nid=0x4a2c runnable [0x000000001f69e000]
   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:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    - locked <0x000000076b849f08> (a java.io.InputStreamReader)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    - locked <0x000000076b849f08> (a java.io.InputStreamReader)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

   Locked ownable synchronizers:
    - None

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001ee32800 nid=0x5b60 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001eddd000 nid=0x5e98 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001edc1000 nid=0x5fa8 in Object.wait() [0x000000001f39e000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000076b588ed8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
    - locked <0x000000076b588ed8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

   Locked ownable synchronizers:
    - None

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001edc0800 nid=0x4860 in Object.wait() [0x000000001f29f000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000076b586c00> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:502)
    at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
    - locked <0x000000076b586c00> (a java.lang.ref.Reference$Lock)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

   Locked ownable synchronizers:
    - None

"VM Thread" os_prio=2 tid=0x000000001cfa9000 nid=0x3914 runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000034da800 nid=0x5b20 runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000000034dc000 nid=0x4b80 runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00000000034dd800 nid=0x5dac runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00000000034df000 nid=0x59b8 runnable 

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00000000034e1800 nid=0x426c runnable 

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00000000034e3800 nid=0x5d3c runnable 

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00000000034e7000 nid=0x2424 runnable 

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00000000034e8000 nid=0x2aec runnable 

"VM Periodic Task Thread" os_prio=2 tid=0x000000001f15d000 nid=0x5c64 waiting on condition 

JNI global references: 12
等待IO

写个简单的等待用户输入例子:

public class Test {

    public static void main(String[] args) throws InterruptedException, IOException {

        InputStream is = System.in;
        int i = is.read();
        System.out.println("exit。");

    }
}

内存溢出

4.jmap

jmap命令是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。
打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。
jmap用来查看堆内存使用状况,一般结合jhat使用。
用于显示当前Java堆和永久代的详细信息(如当前使用的收集器,当前的空间使用率等)

-dump:生成java堆转储快照
-heap:显示java堆详细信息(只在Linux/Solaris下有效)
-F:当虚拟机进程对-dump选项没有响应时,可使用这个选项强制生成dump快照(只在Linux/Solaris下有效)
-finalizerinfo:显示在F-Queue中等待Finalizer线程执行finalize方法的对象(只在Linux/Solaris下有效)
-histo:显示堆中对象统计信息
-permstat:以ClassLoader为统计口径显示永久代内存状态(只在Linux/Solaris下有效)
命令格式:jmap [option] vmid




C:\Users\kpion>jmap -heap 17324
Attaching to process ID 17324, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.231-b11

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

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 4261412864 (4064.0MB)
   NewSize                  = 88604672 (84.5MB)
   MaxNewSize               = 1420296192 (1354.5MB)
   OldSize                  = 177733632 (169.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 = 125829120 (120.0MB)
   used     = 112953408 (107.72076416015625MB)
   free     = 12875712 (12.27923583984375MB)
   89.76730346679688% used
From Space:
   capacity = 8912896 (8.5MB)
   used     = 8912896 (8.5MB)
   free     = 0 (0.0MB)
   100.0% used
To Space:
   capacity = 16777216 (16.0MB)
   used     = 0 (0.0MB)
   free     = 16777216 (16.0MB)
   0.0% used
PS Old Generation
   capacity = 253231104 (241.5MB)
   used     = 36305904 (34.62400817871094MB)
   free     = 216925200 (206.87599182128906MB)
   14.337063428037656% used

20840 interned Strings occupying 2194168 bytes.
将数据导出:

jmap -dump:format=b,file=

jmap -dump:format=b,file=heap.bin 17324
C:\Users\kpion>jmap -dump:format=b,file=heap.bin 17324
Dumping heap to C:\Users\kpion\heap.bin ...
Heap dump file created

这个时候会在当前目录以生成一个heap.bin这个二进制文件。

5.jhat

用于分析使用jmap生成的dump文件,是JDK自带的工具,使用方法为:
jhat -J -Xmx512m [file]

C:\Users\kpion>jhat -J-Xmx1024m heap.bin
Reading from heap.bin...
Dump file created Sat Feb 22 15:59:49 CST 2020
Snapshot read, resolving...
Resolving 2760842 objects...
Chasing references, expect 552 dots........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Eliminating duplicate references........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

访问 http://localhost:7000/ 查看分析结果

image.png

不过jhat没有mat好用,推荐使用mat(Eclipse插件: http://www.eclipse.org/mat ),mat速度更快,而且是图形界面。

MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速、功能丰富的JAVA heap分析工具

使用内存分析工具从众多的对象中进行分析,快速的计算出在内存中对象的占用大小,看看是谁阻止了垃圾收集器的回收工作,并可以通过报表直观的查看到可能造成这种结果的对象。

7.VisualVM的使用

内存溢出

idea VM options配置

-Xms20m -Xmx20m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:\test.hprof
/**
 * @date: 2020/2/22 16:16
 * @author: xionghu
 * @desc: 添加以下参数
 *  VM Args:-Xms20m -Xmx20m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:\test.hprof
 */
public class HeapOOM {

    static class OOMObject {
    }

    public static void main(String[] args) {
        List list = new ArrayList();

        while (true) {
            list.add(new OOMObject());
        }
    }
}
image.png
image.png

你可能感兴趣的:(深入JVM内核10 JDK调优命令)