Java内存泄露的问题调查定位:jmap,jstack的使用等等
参考解答
jstack , jmap 都是jdk中提供的实用工具,用来诊断jvm在运行期间可能发生的问题。
1. jps
它可以用来获取当前系统中运行的所有java进程
例如:
C:\Users\Administrator>jps
会输出:
7520 Jps
2568 Bootstrap
2668
第一列是进程id, 第二列是java应用的名称
注意 这个命令在linux,windows平台下是通用的,只要安装了jdk,配置好环境变量 但如果仅安装了jre,jre并没有自带jps命令,这时linux下可以采用:
ps -fe | grep java
来查看所有java进程,以达到类似目的
2. jstack
它可以用来查询一个进程内所有线程的运行情况
例如:
C:\Users\Administrator>jstack 2568
其中2568是第一步用jps 查询到的java进程id,这里实际上是一个tomcat启动的java进程
会输出:
2017-06-13 16:36:08
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.102-b14 mixed mode):
"http-bio-9090-exec-2" #21 daemon prio=5 os_prio=0 tid=0x000000005a058000 nid=0x1d5c waiting on condition [0x000000006183e000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000dc5a9bb8> (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:104)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:32)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
...
以这一段为例,它的含义是:有一个线程名为 http-bio-9090-exec-2
从名字上可以知道它是一个tomcat中以block-io方式工作线程,线程类型是守护线程
,线程id 是0x1d5c
(16进制),它目前处于等待状态(waiting on condition)
注意 线程id可以配合 ps 命令(linux)或pslist 命令(windows) 来进一步调试
能调试方面有:查看线程的状态、运行时间、CPU占用时间等。
3. jmap
它可以用来查询java heap(堆)内存信息
例如:
jmap -heap 2568
会输出:
Attaching to process ID 6776, 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 = 2118123520 (2020.0MB)
NewSize = 44564480 (42.5MB)
MaxNewSize = 705691648 (673.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 = 219152384 (209.0MB)
used = 40289760 (38.423309326171875MB)
free = 178862624 (170.57669067382812MB)
18.38435852926884% used
From Space:
capacity = 17825792 (17.0MB)
used = 17345968 (16.542404174804688MB)
free = 479824 (0.4575958251953125MB)
97.30825985179229% used
To Space:
capacity = 25690112 (24.5MB)
used = 0 (0.0MB)
free = 25690112 (24.5MB)
0.0% used
PS Old Generation
capacity = 94371840 (90.0MB)
used = 37452712 (35.717689514160156MB)
free = 56919128 (54.282310485839844MB)
39.68632168240018% used
17352 interned Strings occupying 2191288 bytes.
可以看到它能够看到jvm中内存的占用分布情况,新生代、老生代内存分布。
它还可以用来排查每个类型的java对象所占用的内容信息,例如:
jmap -histo 2568
输出内容较多,仅截取一部分:
num #instances #bytes class name
----------------------------------------------
1: 23559 34522152 [B
2: 122540 24184216 [C
3: 3677 3615104 [I
4: 107057 2569368 java.lang.String
5: 13688 1204544 java.lang.reflect.Method
6: 6278 706064 java.lang.Class
7: 18566 594112 java.util.HashMap$Node
...
可以看到它能够统计每种类型对象的个数,占用字节数等