概述
某天系統(tǒng)響應(yīng)變慢需要分析原因昵观,也許我們馬上會(huì)想起java core分析三板斧舀透,top枝冀、pid等等定位到線程使用jstack命令輸出線程堆棧司训。那么如果是內(nèi)存回收不掉的情況呢?也許你的系統(tǒng)已配置-XX HeapDumOnMemoryError独郎,
-XX HeapDumpPath=XXX踩麦,但是一旦如果你沒設(shè)置而且系統(tǒng)并沒內(nèi)存溢出,只是響應(yīng)慢囚聚,回收不理想呢靖榕?這時(shí)候用什么命令呢?當(dāng)然這個(gè)可以現(xiàn)查現(xiàn)用顽铸,但如果是在面試呢茁计?也許你知道但是不記得了,但這個(gè)簡單問題很可能直接會(huì)讓面試官認(rèn)為你沒做過或者不知道,所以簡單整理一下星压。
總結(jié)
一践剂、jmap命令解析與使用
jmap -heap [pid] 查詢內(nèi)存使用情況
[root@fengniaoweb ~]# jmap -heap 2865
Attaching to process ID 2865, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.211-b12
?
using thread-local object allocation.
Parallel GC with 4 thread(s)
?
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 268435456 (256.0MB)
NewSize = 42991616 (41.0MB)
MaxNewSize = 89128960 (85.0MB)
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 = 88080384 (84.0MB)
used = 86317448 (82.31873321533203MB)
free = 1762936 (1.6812667846679688MB)
97.99849192301433% used
From Space:
capacity = 524288 (0.5MB)
used = 32768 (0.03125MB)
free = 491520 (0.46875MB)
6.25% used
To Space:
capacity = 524288 (0.5MB)
used = 0 (0.0MB)
free = 524288 (0.5MB)
0.0% used
PS Old Generation
capacity = 179306496 (171.0MB)
used = 74843440 (71.37626647949219MB)
free = 104463056 (99.62373352050781MB)
41.74050671315332% used
?
26363 interned Strings occupying 3142776 bytes.
要注意的是在使用CMS GC 情況下,jmap -heap的執(zhí)行有可能會(huì)導(dǎo)致JAVA 進(jìn)程掛起
jmap -histo [pid] 查看JVM堆中對象詳細(xì)占用情況
// 限于篇幅僅粘貼示例
3007: 1 16 [Lorg.aspectj.weaver.ast.Var;
3008: 1 16 [Lorg.aspectj.weaver.patterns.AnnotationTypePattern;
3009: 1 16 [Lorg.aspectj.weaver.patterns.BindingPattern;
3010: 1 16 [Lorg.aspectj.weaver.tools.PointcutParameter;
3011: 1 16 [Lorg.springframework.web.context.request.async.CallableProcessingInterceptor;
3012: 1 16 [Lorg.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
3013: 1 16 [Lsun.reflect.annotation.TypeAnnotation$LocationInfo$Location;
3014: 1 16 [[Lorg.aspectj.weaver.AnnotationAJ;
3015: 1 16 com.alibaba.fastjson.parser.deserializer.CharArrayDeserializer
3016: 1 16 com.alibaba.fastjson.parser.deserializer.ClassDerializer
3017: 1 16 com.alibaba.fastjson.parser.deserializer.CollectionDeserializer
3018: 1 16 com.alibaba.fastjson.parser.deserializer.DateDeserializer
3019: 1 16 com.alibaba.fastjson.parser.deserializer.DateFormatDeserializer
3020: 1 16 com.alibaba.fastjson.parser.deserializer.JSONArrayDeserializer
3021: 1 16 com.alibaba.fastjson.parser.deserializer.JSONObjectDeserializer
3022: 1 16 com.alibaba.fastjson.parser.deserializer.JavaObjectDeserializer
3023: 1 16 com.alibaba.fastjson.parser.deserializer.Jdk8DateCodec
3024: 1 16 com.alibaba.fastjson.parser.deserializer.MapDeserializer
3025: 1 16 com.alibaba.fastjson.parser.deserializer.NumberDeserializer
3026: 1 16 com.alibaba.fastjson.parser.deserializer.SqlDateDeserializer
3027: 1 16 com.alibaba.fastjson.parser.deserializer.StackTraceElementDeserializer
3028: 1 16 com.alibaba.fastjson.parser.deserializer.TimeDeserializer
3029: 1 16 com.alibaba.fastjson.parser.deserializer.TimestampDeserializer
jmap -dump:format=b,file=文件名 [pid]
[root@fengniaoweb home]# jmap -dump:format=b,file=heapsim 2865
Dumping heap to /home/heapsim ...
Heap dump file created
[root@fengniaoweb home]# ls
apollo heapsim
[root@fengniaoweb home]#
在當(dāng)前目錄下生成內(nèi)存dump文件
二娜膘、內(nèi)存快照分析工具
jhat java自帶的內(nèi)存快照分析工具 一般不常用逊脯,因?yàn)橛斜緳C(jī)內(nèi)存限制,不易于分析大內(nèi)存文件
eclipse Memory Analyzer
Eclipse 提供的一個(gè)用于分析JVM 堆Dump文件的插件竣贪。借助這個(gè)插件可查看對象的內(nèi)存占用狀況军洼,引用關(guān)系,分析內(nèi)存泄露等演怎。
具體的分析過程不作為本文討論重點(diǎn)匕争,這里就不詳細(xì)討論了。
三爷耀、kill -3 [pid] 輸出線程堆棧信息
當(dāng)系統(tǒng)負(fù)載較高響應(yīng)較慢的時(shí)候或者未安裝jstack命令時(shí)可以使用該命令打印java進(jìn)程堆棧信息甘桑。
如果項(xiàng)目通過Tomcat進(jìn)行發(fā)布(普通的web項(xiàng)目),則對應(yīng)的堆棧信息會(huì)打印在catalina.out文件中歹叮。
如果項(xiàng)目是基于SpringBoot并且使用nohup java -jar xxx.jar & 命令運(yùn)行跑杭,則java堆棧信息會(huì)在jar包所在的nohup.out文件中。
注意:該命令并不會(huì)殺死jvm進(jìn)程
[root@fengniaoweb logs]# kill -3 2865
// 在nohup文件中發(fā)現(xiàn)如下堆棧信息
"JDWP Event Helper Thread" #6 daemon prio=10 os_prio=0 tid=0x00007f80c818f000 nid=0xb3c runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
?
"JDWP Transport Listener: dt_socket" #5 daemon prio=10 os_prio=0 tid=0x00007f80c818b800 nid=0xb3b runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
?
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f80c817f800 nid=0xb3a waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
?
"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f80c814d800 nid=0xb39 in Object.wait() [0x00007f80cc16c000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x00000000f008a960> (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)
?
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f80c814a800 nid=0xb38 in Object.wait() [0x00007f80b1f31000]
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 <0x00000000f008a990> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
?
"VM Thread" os_prio=0 tid=0x00007f80c8141000 nid=0xb37 runnable
?
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f80c8021000 nid=0xb33 runnable
?
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f80c8022800 nid=0xb34 runnable
?
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f80c8024800 nid=0xb35 runnable
?
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f80c8026800 nid=0xb36 runnable
四咆耿、 jstack [pid] jvm自帶的堆棧工具
通過該工具可以看到JVM 中線程的運(yùn)行狀況德谅,包括鎖等待,線程是否在運(yùn)行票灰,線程的所有堆棧信息
[root@fengniaoweb logs]# jstack 2865
Attaching to process ID 2865, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.211-b12
Deadlock Detection:
?
No deadlocks found.
?
Thread 20440: (state = BLOCKED)
?
?
Thread 11659: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Compiled frame; information may be imprecise)
- java.lang.ref.ReferenceQueue.remove(long) @bci=59, line=144 (Compiled frame)
- java.lang.ref.ReferenceQueue.remove() @bci=2, line=165 (Compiled frame)
- org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$ReferenceQueueThread.run() @bci=10, line=1122 (Interpreted frame)
?
?
Thread 10425: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Compiled frame; information may be imprecise)
- java.lang.ref.ReferenceQueue.remove(long) @bci=59, line=144 (Compiled frame)
- com.mysql.jdbc.AbandonedConnectionCleanupThread.run() @bci=10, line=64 (Compiled frame)
- java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95, line=1149 (Interpreted frame)
- java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=624 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=748 (Interpreted frame)
?
?
Thread 10424: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Compiled frame; information may be imprecise)
- java.util.TimerThread.mainLoop() @bci=201, line=552 (Compiled frame)
- java.util.TimerThread.run() @bci=1, line=505 (Interpreted frame)
?
?
Thread 2866: (state = BLOCKED)
?
?
Thread 3079: (state = BLOCKED)
- java.lang.Thread.sleep(long) @bci=0 (Compiled frame; information may be imprecise)
- org.apache.coyote.AbstractProtocol$AsyncTimeout.run() @bci=10, line=1133 (Compiled frame)
- java.lang.Thread.run() @bci=11, line=748 (Interpreted frame)
?
?
Thread 3078: (state = IN_NATIVE)
- sun.nio.ch.ServerSocketChannelImpl.accept0(java.io.FileDescriptor, java.io.FileDescriptor, java.net.InetSocketAddress[]) @bci=0 (Compiled frame; information may be imprecise)
- sun.nio.ch.ServerSocketChannelImpl.accept(java.io.FileDescriptor, java.io.FileDescriptor, java.net.InetSocketAddress[]) @bci=4, line=422 (Compiled frame)
- sun.nio.ch.ServerSocketChannelImpl.accept() @bci=130, line=250 (Compiled frame)
- org.apache.tomcat.util.net.NioEndpoint$Acceptor.run() @bci=88, line=455 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=748 (Interpreted frame)
?
?
Thread 3077: (state = IN_NATIVE)
- sun.nio.ch.EPollArrayWrapper.epollWait(long, int, long, int) @bci=0 (Compiled frame; information may be imprecise)
- sun.nio.ch.EPollArrayWrapper.poll(long) @bci=18, line=269 (Compiled frame)
- sun.nio.ch.EPollSelectorImpl.doSelect(long) @bci=28, line=93 (Compiled frame)
- sun.nio.ch.SelectorImpl.lockAndDoSelect(long) @bci=37, line=86 (Compiled frame)
- sun.nio.ch.SelectorImpl.select(long) @bci=30, line=97 (Compiled frame)
- org.apache.tomcat.util.net.NioEndpoint$Poller.run() @bci=55, line=793 (Compiled frame)
- java.lang.Thread.run() @bci=11, line=748 (Interpreted frame)
?
?
Thread 3076: (state = IN_NATIVE)
- sun.nio.ch.EPollArrayWrapper.epollWait(long, int, long, int) @bci=0 (Compiled frame; information may be imprecise)
- sun.nio.ch.EPollArrayWrapper.poll(long) @bci=18, line=269 (Compiled frame)
- sun.nio.ch.EPollSelectorImpl.doSelect(long) @bci=28, line=93 (Compiled frame)
- sun.nio.ch.SelectorImpl.lockAndDoSelect(long) @bci=37, line=86 (Compiled frame)
- sun.nio.ch.SelectorImpl.select(long) @bci=30, line=97 (Compiled frame)
- org.apache.tomcat.util.net.NioEndpoint$Poller.run() @bci=55, line=793 (Compiled frame)
- java.lang.Thread.run() @bci=11, line=748 (Interpreted frame)
關(guān)于jstack命令的詳細(xì)講解可以參考
https://www.cnblogs.com/xingzc/p/5778010.html
附加:
命令格式 top -Hp pid -d 1 -n 1
打印進(jìn)程號為pid的進(jìn)程所有子線程的cpu女阀,內(nèi)存等資源占用情況宅荤。
該命令結(jié)合線程堆椥加兀可以分析線程資源占用問題