# 查看所有对象,包括活跃以及非活跃的
jmap ‐histo <pid> | more
# 查看活跃对象
jmap ‐histo :live <pid> | more
[root@node01 ~] # jmap ‐histo:live 6219 | more
num #instances #bytes class name
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
1 : 37437 7914608 [C
2 : 34916 837984 java.lang.String
3 : 884 654848 [B
4 : 17188 550016 java.util.HashMap $Node
5 : 3674 424968 java.lang.Class
6 : 6322 395512 [Ljava.lang.Object;
7 : 3738 328944 java.lang.reflect.Method
8 : 1028 208048 [Ljava.util.HashMap $Node ;
9 : 2247 144264 [I
10 : 4305 137760
java.util.concurrent.ConcurrentHashMap $Node
11 : 1270 109080 [Ljava.lang.String;
12 : 64 84128
[Ljava.util.concurrent.ConcurrentHashMap $Node ;
13 : 1714 82272 java.util.HashMap
14 : 3285 70072 [Ljava.lang.Class;
15 : 2888 69312 java.util.ArrayList
16 : 3983 63728 java.lang.Object
17 : 1271 61008
org.apache.tomcat.util.digester.CallMethodRule
18 : 1518 60720 java.util.LinkedHashMap $Entry
19 : 1671 53472
com.sun.org.apache.xerces.internal.xni.QName
20 : 88 50880 [Ljava.util.WeakHashMap $Entry ;
21 : 618 49440 java.lang.reflect.Constructor
22 : 1545 49440 java.util.Hashtable $Entry
23 : 1027 41080 java.util.TreeMap $Entry
24 : 846 40608
org.apache.tomcat.util.modeler.AttributeInfo
25 : 142 38032 [S
26 : 946 37840 java.lang.ref.SoftReference
27 : 226 36816 [[C
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
# 对象说明
B byte
C char
D double
F float
I int
J long
Z boolean
[ 数组,如 [I 表示 int[]
[L + 类名 其他对象
4.3 、将内存使用情况 dump 到文件中
有些时候我们需要将 jvm 当前内存中的情况 dump 到文件中,然后对它进行分析, jmap 也
是支持 dump 到文件中
# 用法:
jmap ‐dump :format = b ,file = dumpFileName <pid>
可以看到已经在 /tmp 下生成了 dump.dat 的文件。
4.4 、通过 jhat 对 dump 文件进行分析
在上一小节中,我们将 jvm 的内存 dump 到文件中,这个文件是一个二进制的文件,不方
便查看,这时我们可以借助于 jhat 工具进行查看。
# 用法:
jhat ‐port <port> <file>
# 示例:
[root@node01 tmp] # jhat ‐port 9999 /tmp/dump.dat
Reading from /tmp/dump.dat...
Dump file created Mon Sep 10 01 :04:21 CST 2018
Snapshot read, resolving...
Resolving 204094 objects...
Chasing references, expect 40
dots........................................
Eliminating duplicate references........................................
Snapshot resolved.
Started HTTP server on port 9999
Server is ready
5 、实战:内存溢出的定位与分析
内存溢出在实际的生产环境中经常会遇到,比如,不断的将数据写入到一个集合中,出
现了死循环,读取超大的文件等等,都可能会造成内存溢出。
如果出现了内存溢出,首先我们需要定位到发生内存溢出的环节,并且进行分析,是正
常还是非正常情况,如果是正常的需求,就应该考虑加大内存的设置,如果是非正常需
求,那么就要对代码进行修改,修复这个 bug 。
首先,我们得先学会如何定位问题,然后再进行分析。如何定位问题呢,我们需要借助
于 jmap 与 MAT 工具进行定位分析。
接下来,我们模拟内存溢出的场景。
5.1 、模拟内存溢出
编写代码,向 List 集合中添加 100 万个字符串,每个字符串由 1000 个 UUID 组成。如果程
序能够正常执行,最后打印 ok 。
public class TestJvmOutOfMemory {
public static void main ( String [] args ) {
List< Object > list = new ArrayList<> ();
for ( int i = 0 ; i < 10000000 ; i++ ) {
String str = "" ;
for ( int j = 0 ; j < 1000 ; j++ ) {
str += UUID . randomUUID (). toString ();
}
list . add ( str );
}
System . out . println ( "ok" );
}
}
6 、 jstack 的使用
有些时候我们需要查看下 jvm 中的线程执行情况,比如,发现服务器的 CPU 的负载突然增
高了、出现了死锁、死循环等,我们该如何分析呢?
由于程序是正常运行的,没有任何的输出,从日志方面也看不出什么问题,所以就需要
看下 jvm 的内部线程的执行情况,然后再进行分析查找出原因。
这个时候,就需要借助于 jstack 命令了, jstack 的作用是将正在运行的 jvm 的线程情况进
行快照,并且打印出来:
# 用法: jstack <pid>
[root@node01 bin] # jstack 2203
Full thread dump Java HotSpot(TM) 64 ‐Bit Server VM (25.141‐b15 mixed
mode):