Java 與 C++ 之間有一堵由內(nèi)存動(dòng)態(tài)分配和垃圾收集技術(shù)所圍成的高強(qiáng),墻外面的人想進(jìn)去,墻里面的人想出來(lái).
4.1 概述
理論總是作為指導(dǎo)實(shí)踐的工具,能把這些知識(shí)應(yīng)用到實(shí)際工作中才是我們的最終目的.
給一個(gè)系統(tǒng)定位問(wèn)題的時(shí)候,知識(shí)/經(jīng)驗(yàn)是關(guān)鍵基礎(chǔ), 數(shù)據(jù)是依據(jù), 工具是運(yùn)用知識(shí)處理數(shù)據(jù)的手段.
數(shù)據(jù)包括: 運(yùn)行日志, 異常堆棧, GC日志, 線程快照, 堆轉(zhuǎn)儲(chǔ)快照等.
經(jīng)常使用適當(dāng)?shù)奶摂M機(jī)監(jiān)控和分析的工具可以加快我們分析數(shù)據(jù),定位解決問(wèn)題的速度.
4.2 JDK的命令行工具
表:Sun JDK 監(jiān)控和故障處理工具
名稱 | 主要作用 |
---|---|
jps | JVM Process Status Tool, 顯示指定系統(tǒng)內(nèi)所有的HotSpot 虛擬機(jī)進(jìn)程 |
jstat | JVM Statistics Monitoring Tool, 用于收集 HotSpot 虛擬機(jī)各方面的運(yùn)行數(shù)據(jù) |
jinfo | Configuration Info for Java, 顯示虛擬機(jī)配置信息 |
jmap | Memory Map for Java, 生成虛擬機(jī)的內(nèi)存轉(zhuǎn)儲(chǔ)快照(headdump 文件) |
jhat | JVM Heap Dump Browser, 用于分析heapdump 文件,它會(huì)建立一個(gè)HTTP/HTML 服務(wù)器, 讓用戶可以在瀏覽器上查看分析結(jié)果 |
jstack | Stack Trace for Java, 顯示虛擬機(jī)的線程快照 |
4.2.1 jps: 虛擬機(jī)進(jìn)程狀態(tài)工具
jps: 列出正在運(yùn)行的虛擬機(jī)進(jìn)程,并顯示虛擬機(jī)執(zhí)行主類(Main Class, main()函數(shù)所在的類)名稱以及這些進(jìn)程的本地虛擬機(jī)唯一ID(Local Virtual Machine Identifier, LVMID).
jps 命令格式: jps [options] [hostid]
jps 執(zhí)行樣例:
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jps -l
30096 blog-0.0.1-SNAPSHOT.jar
13242 sun.tools.jps.Jps
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jps -q
30096
13254
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jps -m
30096 jar
13266 Jps -m
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jps -v
30096 jar
13278 Jps -Denv.class.path=.:/usr/java/jdk1.8.0_161/lib:/usr/java/jdk1.8.0_161/jre/lib -Dapplication.home=/usr/java/jdk1.8.0_161 -Xms8m
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jps -lv
30096 blog-0.0.1-SNAPSHOT.jar
13292 sun.tools.jps.Jps -Denv.class.path=.:/usr/java/jdk1.8.0_161/lib:/usr/java/jdk1.8.0_161/jre/lib -Dapplication.home=/usr/java/jdk1.8.0_161 -Xms8m
表: jps 工具主要選項(xiàng)
選項(xiàng) | 作用 |
---|---|
-q | 只輸出 LVMID, 省略主類的名稱 |
-m | 輸出虛擬機(jī)進(jìn)程啟動(dòng)時(shí)傳遞給主類main() 函數(shù)的參數(shù) |
-l | 輸出主類的全名, 如果進(jìn)程執(zhí)行的是Jar包,輸出 Jar路徑 |
-v | 輸出虛擬機(jī)進(jìn)程啟動(dòng)時(shí)JVM參數(shù) |
4.2.2 jstat: 虛擬機(jī)統(tǒng)計(jì)信息監(jiān)視工具
jstat(JVM Statistics Monitoring Tool) 是用于監(jiān)視虛擬機(jī)各種運(yùn)行狀態(tài)信息的命令行工具. 它可以顯示本地或者遠(yuǎn)程虛擬機(jī)進(jìn)程中的類裝載,內(nèi)存,垃圾收集,JIT編譯等運(yùn)行數(shù)據(jù), 在沒(méi)有GUI圖形界面,只提供了純文本控制臺(tái)環(huán)境的服務(wù)器上,它將是運(yùn)行期定位虛擬機(jī)性能問(wèn)題的首選工具.
jstat 命令格式: jstat [option vmid [interval [s | ms] [count] ]]
假設(shè)需要每250毫秒查詢一次進(jìn)程2764的垃圾收集情況, 一共查詢20次:
jstat -gc 2764 250 20
表: jstat 工具主要選項(xiàng)
選項(xiàng) | 作用 |
---|---|
-class | 監(jiān)視類裝載,卸載數(shù)量,總空間以及類裝載所耗費(fèi)的時(shí)間 |
-gc | 監(jiān)視Java堆狀況,包括Eden區(qū), 兩個(gè)Survivor區(qū),老年代,永久代等的容量,已用空間,GC時(shí)間合計(jì)等信息 |
-gccapacity | 監(jiān)視內(nèi)容與-gc基本相同,但輸出主要專注Java堆各個(gè)區(qū)域使用到的最大,最小空間 |
-gcutil | 監(jiān)視內(nèi)容與 -gc 基本相同, 但輸出主要關(guān)注已使用空間占總空間的百分比 |
-gccause | 與 -gcutil 功能一樣,但是會(huì)額外輸出導(dǎo)致上一次GC產(chǎn)生的原因 |
-gcnew | 監(jiān)視新生代GC狀況 |
-gcnewcapacity | 監(jiān)視內(nèi)容與 -gcnew 基本相同,輸出主要關(guān)注使用到的最大,最小空間 |
-gcold | 監(jiān)視老年代GC狀況 |
-gcoldcapacity | 監(jiān)視內(nèi)容與i -gcold 基本相同,輸出主要關(guān)注使用到的最大,最小空間 |
-gcpermcapacity | 輸出永久代使用到的最大,最小空間 |
-compiler | 輸出JIT 編譯器編譯過(guò)的方法,耗時(shí)等信息 |
-printcompilation | 輸出已經(jīng)被JIT編譯的方法 |
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jstat -class 30096
Loaded Bytes Unloaded Bytes Time
11647 21454.1 0 0.0 19.01
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jstat -gc 30096
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
2624.0 2624.0 100.6 0.0 21184.0 6007.8 52748.0 49099.7 65968.0 64808.9 8112.0 7844.3 378 2.038 3 0.311 2.349
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jstat -gccapacity 30096
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
10880.0 171328.0 26432.0 2624.0 2624.0 21184.0 21888.0 342720.0 52748.0 52748.0 0.0 1107968.0 65968.0 0.0 1048576.0 8112.0 378 3
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jstat -gcutil 30096
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
3.84 0.00 28.36 93.08 98.24 96.70 378 2.038 3 0.311 2.349
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jstat -gccause 30096
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC
3.84 0.00 28.36 93.08 98.24 96.70 378 2.038 3 0.311 2.349 Allocation Failure No GC
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jstat -gcnew 30096
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
2624.0 2624.0 100.6 0.0 15 15 1312.0 21184.0 6007.8 378 2.038
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jstat -gcold 30096
MC MU CCSC CCSU OC OU YGC FGC FGCT GCT
65968.0 64808.9 8112.0 7844.3 52748.0 49099.7 378 3 0.311 2.349
linyk3@aliyun02:/usr/java/jdk1.8.0_161/bin$ jstat -compiler 30096
Compiled Failed Invalid Time FailedType FailedMethod
11317 1 0 58.19 1 com/mysql/jdbc/AbandonedConnectionCleanupThread run
4.2.3 jinfo: Java 配置信息工具
jinfo(Configuration Info for Java) 的作用是實(shí)時(shí)的查看和調(diào)整虛擬機(jī)各項(xiàng)參數(shù).
jinfo 命令格式: jinfo [ option ] pid
執(zhí)行樣例:
linyk3@aliyun02:~$ jinfo -flag CMSInitiatingOccupancyFraction 30096
-XX:CMSInitiatingOccupancyFraction=-1
4.2.4 jmap : Java 內(nèi)存映像工具
jmap(Memory Map for Java) 命令用于生成堆轉(zhuǎn)儲(chǔ)快照(一般稱為 heapdump 或 dump 文件).
jmap 的作用不僅僅是為了獲取dump文件,它還可以查詢finalize執(zhí)行隊(duì)列, Java堆和永久代的詳細(xì)信息,如空間使用率,當(dāng)前使用的是哪種收集器等.
jmap 命令格式: jmap [ option ] vmid
表: jmap 工具的主要選項(xiàng)
選項(xiàng) | 作用 |
---|---|
-dump | 生成Java堆轉(zhuǎn)儲(chǔ)快照. 格式為 -dump:[live, ] format=b, file=<filename>, 其中l(wèi)ive子參數(shù)說(shuō)明是否只dump出存活的對(duì)象 |
-finalizerinfo | 顯示在F-Queue 中等待 Finalizer 線程執(zhí)行 finalize 方法的對(duì)象. 只在 Linux/Solaris 平臺(tái)下有效 |
-heap | 顯示Java堆詳細(xì)信息, 如使用何種收集器,參數(shù)配置,分代狀況等.只在Linux/Solaris平臺(tái)下有效 |
-histo | 顯示堆中對(duì)象統(tǒng)計(jì)信息, 包括類,實(shí)列對(duì)象,合計(jì)容量 |
-permstat | 以ClassLoader 為統(tǒng)計(jì)口徑顯示永久代內(nèi)存狀態(tài). 只在Linux/Solaris平臺(tái)下有效 |
-F | 當(dāng)虛擬機(jī)進(jìn)程對(duì) -dump 選項(xiàng)沒(méi)有響應(yīng)時(shí), 可使用這個(gè)選項(xiàng)強(qiáng)制生成 dump 快照. 只在 Linux/Solaris 平臺(tái)下有效 |
linyk3@aliyun02:~$ jps -l
30096 blog-0.0.1-SNAPSHOT.jar
16257 sun.tools.jps.Jps
linyk3@aliyun02:~$
linyk3@aliyun02:~$ jmap -dump:format=b,file=blog.bin 30096
Dumping heap to /home/linyk3/blog.bin ...
Heap dump file created
linyk3@aliyun02:~$
4.2.5 jhat: 虛擬機(jī)堆轉(zhuǎn)儲(chǔ)快照分析工具
Sun JDK 提供 jhat(JVM Heap Analysis Tool) 命令與 jmap 搭配使用,來(lái)分析jmap 生成的堆轉(zhuǎn)儲(chǔ)快照.
linyk3@aliyun02:~$ jhat blog
blog/ blog.bin
linyk3@aliyun02:~$ jhat blog.bin
Reading from blog.bin...
Dump file created Tue Jan 21 00:59:03 CST 2020
Snapshot read, resolving...
Resolving 1125167 objects...
Chasing references, expect 225 dots.................................................................................................................................................................................................................................
Eliminating duplicate references.................................................................................................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
當(dāng) 提示"Server is ready" 時(shí), 訪問(wèn)服務(wù)器http://locolhost:7000/ 就可以看到分析結(jié)果了
分析內(nèi)存泄漏只要是用到其中的 "heap histogram"
4.2.6 jstack : Java 堆棧跟蹤工具
jstack(Stack Trace for Java)命令用于生成虛擬機(jī)擋墻時(shí)刻的線程快照(一般稱為threaddump或者javacore文件).
線程快照就是當(dāng)前虛擬機(jī)內(nèi)每一條線程正在執(zhí)行的方法堆棧的集合,生成線程快照的主要目的就是定位線程出現(xiàn)長(zhǎng)時(shí)間停頓的原因,如線程間鎖死, 死循環(huán), 請(qǐng)求外部資源導(dǎo)致的長(zhǎng)時(shí)間等待等都是導(dǎo)致線程長(zhǎng)時(shí)間停頓的常見原因.
線程出現(xiàn)停頓的時(shí)候,通過(guò)jstack來(lái)查看各個(gè)線程的調(diào)用堆棧,就可以知道沒(méi)有響應(yīng)的線程到底在后臺(tái)做些什么事, 或者等待著什么資源.
jstack 命令格式: jstack [ option ] vmid
表: jstack 工具主要選項(xiàng)
選項(xiàng) | 作用 |
---|---|
-F | 當(dāng)正常輸出的請(qǐng)求不被響應(yīng)時(shí), 強(qiáng)制輸出線程堆棧 |
-l | 除堆棧外,顯示關(guān)于鎖的附加消息 |
-m | 如果調(diào)用到本地方法的話, 可以顯示C/C++的堆棧 |
linyk3@aliyun02:~$ jstack -l 30096
2020-01-21 01:20:55
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.161-b12 mixed mode):
"Attach Listener" #34 daemon prio=9 os_prio=0 tid=0x00007f503802b000 nid=0x3eed waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"logback-1" #33 daemon prio=5 os_prio=0 tid=0x00007f5034558000 nid=0x75d2 waiting on condition [0x00007f502bbbc000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000edb37bd8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"DestroyJavaVM" #32 prio=5 os_prio=0 tid=0x00007f505c00a800 nid=0x7592 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"http-nio-9001-AsyncTimeout" #30 daemon prio=5 os_prio=0 tid=0x00007f505e36d800 nid=0x75c9 waiting on condition [0x00007f502bebd000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.coyote.AbstractProtocol$AsyncTimeout.run(AbstractProtocol.java:1211)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-Acceptor-0" #29 daemon prio=5 os_prio=0 tid=0x00007f505e8ad000 nid=0x75c8 runnable [0x00007f502bfbe000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
- locked <0x00000000ed9fead0> (a java.lang.Object)
at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:455)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-ClientPoller-0" #28 daemon prio=5 os_prio=0 tid=0x00007f505d103800 nid=0x75c7 runnable [0x00007f502c0bf000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x00000000eda5c8a0> (a sun.nio.ch.Util$3)
- locked <0x00000000eda5c8b0> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000eda5c858> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:787)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-exec-10" #27 daemon prio=5 os_prio=0 tid=0x00007f505ca4d000 nid=0x75c6 waiting on condition [0x00007f502c1c0000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ed9feae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-exec-9" #26 daemon prio=5 os_prio=0 tid=0x00007f505e79e800 nid=0x75c5 waiting on condition [0x00007f502c2c1000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ed9feae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-exec-8" #25 daemon prio=5 os_prio=0 tid=0x00007f505c15a800 nid=0x75c4 waiting on condition [0x00007f502c3c2000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ed9feae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-exec-7" #24 daemon prio=5 os_prio=0 tid=0x00007f505c9df800 nid=0x75c3 waiting on condition [0x00007f502c4c3000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ed9feae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-exec-6" #23 daemon prio=5 os_prio=0 tid=0x00007f505d03f800 nid=0x75c2 waiting on condition [0x00007f502c5c4000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ed9feae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-exec-5" #22 daemon prio=5 os_prio=0 tid=0x00007f505e51e000 nid=0x75c1 waiting on condition [0x00007f502c6c5000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ed9feae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-exec-4" #21 daemon prio=5 os_prio=0 tid=0x00007f505e5a3000 nid=0x75c0 waiting on condition [0x00007f502c7c6000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ed9feae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-exec-3" #20 daemon prio=5 os_prio=0 tid=0x00007f505c387000 nid=0x75bf waiting on condition [0x00007f502c8c7000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ed9feae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-exec-2" #19 daemon prio=5 os_prio=0 tid=0x00007f505c386000 nid=0x75be waiting on condition [0x00007f502c9c8000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ed9feae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"http-nio-9001-exec-1" #18 daemon prio=5 os_prio=0 tid=0x00007f505c333000 nid=0x75bd waiting on condition [0x00007f504c1fd000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ed9feae0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"NioBlockingSelector.BlockPoller-1" #17 daemon prio=5 os_prio=0 tid=0x00007f505cdb6000 nid=0x75bc runnable [0x00007f502e0cd000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x00000000ed9fed78> (a sun.nio.ch.Util$3)
- locked <0x00000000ed9fed88> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000ed9fed30> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run(NioBlockingSelector.java:339)
Locked ownable synchronizers:
- None
"Abandoned connection cleanup thread" #16 daemon prio=5 os_prio=0 tid=0x00007f505cd44800 nid=0x75a4 in Object.wait() [0x00007f502dac9000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x00000000ec550f60> (a java.lang.ref.ReferenceQueue$Lock)
at com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:64)
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:
- <0x00000000ec550ff0> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"Tomcat JDBC Pool Cleaner[1804094807:1576085386247]" #15 daemon prio=5 os_prio=0 tid=0x00007f505ccfe800 nid=0x75a3 in Object.wait() [0x00007f502dbca000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.util.TimerThread.mainLoop(Timer.java:552)
- locked <0x00000000ec5511a0> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
Locked ownable synchronizers:
- None
"container-0" #14 prio=5 os_prio=0 tid=0x00007f505cb90800 nid=0x75a2 waiting on condition [0x00007f502decb000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.catalina.core.StandardServer.await(StandardServer.java:427)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer$1.run(TomcatEmbeddedServletContainer.java:177)
Locked ownable synchronizers:
- None
"ContainerBackgroundProcessor[StandardEngine[Tomcat]]" #13 daemon prio=5 os_prio=0 tid=0x00007f505cb92000 nid=0x75a1 waiting on condition [0x00007f502dfcc000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1355)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007f505c0dc000 nid=0x7599 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f505c0d8800 nid=0x7598 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f505c0d6800 nid=0x7597 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f505c0d2800 nid=0x7596 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f505c0a2000 nid=0x7595 in Object.wait() [0x00007f504cd24000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x00000000eb17c9c0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f505c09d800 nid=0x7594 in Object.wait() [0x00007f504ce25000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000000eb17cb78> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=0 tid=0x00007f505c096000 nid=0x7593 runnable
"VM Periodic Task Thread" os_prio=0 tid=0x00007f505c0e1000 nid=0x759a waiting on condition
JNI global references: 289
linyk3@aliyun02:~$
4.2.7 HSDIS: JIT 生成代碼反匯編
在Java虛擬機(jī)規(guī)范中, 詳細(xì)描述了虛擬機(jī)指令集中每條指令的執(zhí)行過(guò)程,執(zhí)行前后對(duì)操作數(shù)棧,局部變量表的影響等細(xì)節(jié).
分析程序如何執(zhí)行,通過(guò)軟件調(diào)試工具(GDB, Windbg)來(lái)斷點(diǎn)調(diào)試是最常見的手段.但是在調(diào)試Java虛擬機(jī)會(huì)遇到很大困難.
HSDIS 是一個(gè) Sun 官方推薦的 HotSpot 虛擬機(jī) JIT 編譯代碼的反匯編插件.它的作用是讓HotSpot的-XX:+PrintAssembly 指令調(diào)用它來(lái)把動(dòng)態(tài)生成的本地代碼還原為匯編代碼輸出,同時(shí)還生成大量非常有價(jià)值的注釋,這樣我們就可以通過(guò)輸出的代碼來(lái)分析問(wèn)題.
4.3 JDK 可視化工具
JDK中除了提供大量的命令行工具,還有兩個(gè)功能強(qiáng)大的可視化工具: JConsole 和 VisualVM.
JConsole: JDK 1.5 就以及提供的虛擬機(jī)監(jiān)控工具
VisualVM: JDK1.6 Update7中才首次發(fā)布. 現(xiàn)在已經(jīng)成為主力推動(dòng)的多合一故障處理工具.
4.3.1 JConsole: Java 監(jiān)視與管理控制臺(tái)
-
啟動(dòng):
image.png
4.3.2 VisualVM: 多合一故障處理工具
VisualVM(All-In-One Java Troubleshooting Tool)是到目前為止隨JDK發(fā)布的功能最強(qiáng)大的運(yùn)行監(jiān)視和故障處理程序.
VisualVM 基于 NetBeans 平臺(tái)開發(fā), 所以具備了插件擴(kuò)展功能:
- 顯示虛擬機(jī)進(jìn)程以及進(jìn)程的配置,環(huán)境信息(jps, jinfo)
- 2.監(jiān)視應(yīng)用程序的CPU, GC, 堆, 方法區(qū)以及線程的信息(jstat, jstack)
- 3.dump 以及分析堆轉(zhuǎn)儲(chǔ)快照(jmap, jhat)
- 4.方法級(jí)的程序運(yùn)行性能分析,找出被調(diào)用最多,運(yùn)行時(shí)間最長(zhǎng)的方法
- 5.離線程序快照: 手機(jī)程序的運(yùn)行時(shí)配置, 線程dump, 內(nèi)存 dump等信息建立一個(gè)快照, 可以將快照發(fā)送開發(fā)者進(jìn)行bug反饋.
- 6.其他 plugins 的無(wú)限可能性
4.4 本章小結(jié)
本章介紹了隨JDK發(fā)布的6個(gè)命令行工具以及兩個(gè)可視化的故障處理工具,靈活使用這些工具可以給問(wèn)題處理帶來(lái)很大的便利.
除了JDK自帶的工具外,常用的故障處理工具還有很多.