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
...

可以看到它能够统计每种类型对象的个数,占用字节数等


results matching ""

    No results matching ""