目录
一、jmap:导出内存映像文件&内存使用情况
二、导出dump堆转储快照文件
三、显示堆内存相关信息
四、其它作用
五、小结
一、jmap:导出内存映像文件&内存使用情况
jmap(JVM Memory Map):一方面是获取dump文件(堆转储快照文件,二进制文件),还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。开发人员可以在控制台中输入命令“jmap -help”查阅jmap工具的具体使用方式和一些标准选项配置。
C:\Users\WSH>jmap -h
Usage:
jmap [option] <pid>
(to connect to running process)
jmap [option] <executable <core>
(to connect to a core file)
jmap [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)
where <option> is one of:
<none> to print same info as Solaris pmap
-heap to print java heap summary
-histo[:live] to print histogram of java object heap; if the "live"
suboption is specified, only count live objects
-clstats to print class loader statistics
-finalizerinfo to print information on objects awaiting finalization
-dump:<dump-options> to dump java heap in hprof binary format
dump-options:
live dump only live objects; if not specified,
all objects in the heap are dumped.
format=b binary format
file=<file> dump heap to <file>
Example: jmap -dump:live,format=b,file=heap.bin <pid>
-F force. Use with -dump:<dump-options> <pid> or -histo
to force a heap dump or histogram when <pid> does not
respond. The "live" suboption is not supported
in this mode.
-h | -help to print this help message
-J<flag> to pass <flag> directly to the runtime system
官方帮助文档:jmap
基本使用语法为:
- jmap [option] <pid>
- jmap [option] <executable <core>
- jmap [option] [server_id@] <remote server IP or hostname>
option参数说明如下:
选项 | 作用 |
-dump | 生成dump文件(Java堆转储快照),-dump:live只保存堆中的存活对象 |
-heap | 输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等 |
-histo | 输出堆空间中对象的统计信息,包括类、实例数量和合计容量,-histo:live只统计堆中的存活对象 |
-J <flag> | 传递参数给jmap启动的jvm |
-finalizerinfo | 显示在F-Queue中等待Finalizer线程执行finalize方法的对象,仅linux/solaris平台有效 |
-permstat | 以ClassLoader为统计口径输出永久代的内存状态信息,仅linux/solaris平台有效 |
-F | 当虚拟机进程对-dump选项没有任何响应时,强制执行生成dump文件,仅linux/solaris平台有效 |
说明:这些参数和linux下输入显示的命令多少会有不同,包括也受jdk版本的影响。
二、导出dump堆转储快照文件
dump堆转储快照文件主要有手动和自动两种方式:
【a】手动方式
手动dump出堆转储快照文件:如下两个选择其一即可
//dump出所有对象
> jmap -dump:format=b,file=<filename.hprof> <pid>
//只dump出存活对象(live)
> jmap -dump:live,format=b,file=<filename.hprof> <pid>
示例:
public class GCTest {
public static void main(String[] args) throws ClassNotFoundException {
List<byte[]> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
byte[] arr = new byte[1024 * 100];
list.add(arr);
try {
Thread.sleep(120);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
设置JVM参数并启动程序:
-Xms60m -Xmx60m -XX:SurvivorRatio=8
手动dump出堆转储快照文件:
C:\Users\WSH>jmap -dump:format=b,file=d:\1.hprof 14904
Dumping heap to D:\1.hprof ...
Heap dump file created
C:\Users\WSH>jmap -dump:format=b,file=d:\2.hprof 14904
Dumping heap to D:\2.hprof ...
Heap dump file created
C:\Users\WSH>jmap -dump:format=b,file=d:\3.hprof 14904
Dumping heap to D:\3.hprof ...
Heap dump file created
##########只dump存活的对象###########
C:\Users\WSH>jmap -dump:live,format=b,file=d:\4.hprof 14904
Dumping heap to D:\4.hprof ...
Heap dump file created
如下图,即为生成的堆转储快照文件,可借助一些可视化分析工具打开,后面我们会介绍。
【b】自动方式
- -XX:+HeapDumpOnOutOfMemoryError:在堆溢出的时候可以储存快照;
- -XX:HeapDumpPath=d:/dumps/:导出内存快照时保存的路径;
在启动程序的时候指定上述两个参数即可,如下图:
三、显示堆内存相关信息
【a】jmap -heap 928:查看堆各区域的使用情况
C:\Users\WSH>jmap -heap 928
Attaching to process ID 928, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.291-b10
using thread-local object allocation.
Parallel GC with 10 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 62914560 (60.0MB)
NewSize = 20971520 (20.0MB)
MaxNewSize = 20971520 (20.0MB)
OldSize = 41943040 (40.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 = 15728640 (15.0MB)
used = 1623088 (1.5478973388671875MB)
free = 14105552 (13.452102661132812MB)
10.319315592447916% used
From Space:
capacity = 2621440 (2.5MB)
used = 2589008 (2.4690704345703125MB)
free = 32432 (0.0309295654296875MB)
98.7628173828125% used
To Space:
capacity = 2621440 (2.5MB)
used = 0 (0.0MB)
free = 2621440 (2.5MB)
0.0% used
PS Old Generation
capacity = 41943040 (40.0MB)
used = 10146216 (9.676185607910156MB)
free = 31796824 (30.323814392089844MB)
24.19046401977539% used
3182 interned Strings occupying 260960 bytes.
【b】jmap -histo 928:查看实例柱数状图
C:\Users\WSH>jmap -histo 928
num #instances #bytes class name
----------------------------------------------
1: 775 31478280 [B
2: 5082 526064 [C
3: 169 418184 [I
4: 4933 118392 java.lang.String
5: 717 82248 java.lang.Class
6: 681 47240 [Ljava.lang.Object;
7: 791 31640 java.util.TreeMap$Entry
8: 720 28800 java.util.LinkedHashMap$Entry
9: 427 18984 [Ljava.lang.String;
10: 521 16672 java.util.HashMap$Node
11: 179 11456 java.net.URL
12: 26 10720 [Ljava.util.HashMap$Node;
13: 113 8136 java.lang.reflect.Field
14: 211 5064 java.util.LinkedList$Node
15: 52 4992 java.util.jar.JarFile$JarFileEntry
16: 88 4928 sun.misc.URLClassPath$JarLoader
17: 61 4880 [Ljava.util.WeakHashMap$Entry;
18: 115 4600 java.lang.ref.Finalizer
19: 110 4400 java.lang.ref.SoftReference
20: 256 4096 java.lang.Integer
21: 123 3936 java.util.Hashtable$Entry
22: 58 3712 java.util.jar.JarFile
23: 111 3552 java.util.concurrent.ConcurrentHashMap$Node
24: 107 3424 java.util.LinkedList
25: 61 3416 sun.nio.cs.UTF_8$Encoder
26: 133 3192 java.io.ExpiringCache$Entry
27: 8 3008 java.lang.Thread
28: 61 2928 java.util.WeakHashMap
29: 48 2304 java.util.zip.Inflater
30: 56 2240 sun.nio.cs.UTF_8$Decoder
31: 68 2176 java.lang.ref.ReferenceQueue
32: 26 2080 java.lang.reflect.Constructor
33: 16 2048 [Ljava.util.concurrent.ConcurrentHashMap$Node;
34: 39 1872 sun.util.locale.LocaleObjectCache$CacheEntry
35: 58 1856 java.util.zip.ZipCoder
36: 36 1728 java.util.HashMap
37: 1 1568 [[B
38: 37 1480 java.io.ObjectStreamField
39: 26 1456 java.lang.Class$ReflectionData
40: 89 1424 java.lang.Object
41: 58 1392 java.util.ArrayDeque
42: 20 1280 java.util.concurrent.ConcurrentHashMap
43: 9 1184 [Ljava.util.Hashtable$Entry;
44: 48 1152 java.util.zip.ZStreamRef
45: 70 1120 java.lang.ref.ReferenceQueue$Lock
46: 2 1064 [Ljava.lang.invoke.MethodHandle;
47: 1 1040 [Ljava.lang.Integer;
48: 1 1040 [[C
49: 19 760 sun.util.locale.BaseLocale$Key
50: 11 648 [Ljava.lang.reflect.Field;
51: 8 640 [S
52: 19 608 java.io.File
53: 19 608 java.util.Locale
54: 19 608 sun.util.locale.BaseLocale
55: 13 520 java.security.AccessControlContext
56: 21 504 java.util.jar.Attributes$Name
57: 19 456 java.util.Locale$LocaleKey
58: 18 432 sun.misc.MetaIndex
59: 13 392 [Ljava.io.ObjectStreamField;
60: 1 384 com.intellij.rt.execution.application.AppMainV2$1
61: 1 384 java.lang.ref.Finalizer$FinalizerThread
62: 6 384 java.nio.DirectByteBuffer
63: 1 376 java.lang.ref.Reference$ReferenceHandler
64: 18 352 [Ljava.lang.Class;
65: 6 336 java.nio.DirectLongBufferU
66: 10 320 java.lang.OutOfMemoryError
67: 3 312 [D
68: 2 312 [J
69: 13 312 [Ljava.lang.reflect.Constructor;
70: 13 312 sun.reflect.NativeConstructorAccessorImpl
71: 12 288 java.util.ArrayList
72: 5 280 sun.util.calendar.ZoneInfo
73: 3 264 java.lang.reflect.Method
74: 11 264 java.net.StandardSocketOptions$StdSocketOption
75: 8 256 java.util.Vector
76: 3 240 [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;
77: 5 240 java.util.Hashtable
78: 7 224 java.lang.ThreadLocal$ThreadLocalMap$Entry
79: 4 224 java.util.LinkedHashMap
80: 13 208 sun.reflect.DelegatingConstructorAccessorImpl
81: 5 200 java.security.ProtectionDomain
82: 5 200 java.util.WeakHashMap$Entry
83: 6 192 java.nio.file.attribute.FileTime
84: 4 192 java.util.Properties
85: 4 192 java.util.TreeMap
86: 2 160 [[Ljava.lang.String;
87: 4 160 java.io.FileDescriptor
88: 4 160 java.lang.ClassLoader$NativeLibrary
89: 5 160 java.security.CodeSource
90: 5 160 sun.util.locale.provider.LocaleProviderAdapter$Type
91: 3 144 java.nio.HeapByteBuffer
92: 6 144 sun.misc.PerfCounter
93: 3 144 sun.misc.URLClassPath
94: 2 128 java.io.ExpiringCache$1
95: 4 128 java.util.Stack
96: 2 128 sun.nio.cs.ext.DoubleByte$Encoder
97: 1 120 java.net.SocksSocketImpl
98: 5 120 java.util.Collections$UnmodifiableRandomAccessList
99: 5 120 sun.misc.FloatingDecimal$PreparedASCIIToBinaryBuffer
100: 2 112 java.lang.Package
101: 7 112 java.util.HashSet
102: 2 112 java.util.ResourceBundle$CacheKey
103: 2 112 sun.nio.cs.ext.DoubleByte$Decoder
104: 4 96 java.lang.RuntimePermission
105: 3 96 java.lang.StringCoding$StringEncoder
106: 2 96 java.lang.ThreadGroup
107: 6 96 java.lang.ThreadLocal
108: 1 96 java.net.DualStackPlainSocketImpl
109: 2 96 java.util.ResourceBundle$BundleReference
110: 4 96 jdk.net.ExtendedSocketOptions$ExtSocketOption
111: 1 96 sun.misc.Launcher$AppClassLoader
112: 3 96 sun.net.spi.DefaultProxySelector$NonProxyInfo
113: 2 96 sun.nio.cs.StreamEncoder
114: 1 88 sun.misc.Launcher$ExtClassLoader
115: 5 80 [Ljava.security.Principal;
116: 2 80 java.io.BufferedWriter
117: 2 80 java.io.ExpiringCache
118: 5 80 java.security.ProtectionDomain$Key
119: 2 80 sun.misc.FloatingDecimal$BinaryToASCIIBuffer
120: 3 72 java.lang.ThreadLocal$ThreadLocalMap
121: 3 72 java.net.Proxy$Type
122: 3 72 java.util.Arrays$ArrayList
123: 1 72 java.util.ResourceBundle$RBClassLoader
124: 3 72 java.util.concurrent.atomic.AtomicLong
125: 3 72 sun.misc.FloatingDecimal$ExceptionalBinaryToASCIIBuffer
126: 1 72 sun.util.locale.provider.JRELocaleProviderAdapter
127: 1 64 [F
128: 2 64 [Ljava.lang.Thread;
129: 2 64 java.io.FileOutputStream
130: 2 64 java.io.FilePermission
131: 2 64 java.io.PrintStream
132: 2 64 java.lang.ClassValue$Entry
133: 2 64 java.lang.StringCoding$StringDecoder
134: 2 64 java.lang.VirtualMachineError
135: 2 64 java.lang.ref.ReferenceQueue$Null
136: 2 64 java.lang.ref.WeakReference
137: 2 64 java.security.BasicPermissionCollection
138: 2 64 java.security.Permissions
139: 2 64 java.util.ResourceBundle$LoaderReference
140: 2 48 [Ljava.lang.reflect.Method;
141: 1 48 [Ljava.util.concurrent.TimeUnit;
142: 2 48 java.io.BufferedOutputStream
143: 1 48 java.io.BufferedReader
144: 2 48 java.io.File$PathStatus
145: 2 48 java.io.FilePermissionCollection
146: 2 48 java.io.OutputStreamWriter
147: 2 48 java.net.InetAddress$Cache
148: 2 48 java.net.InetAddress$Cache$Type
149: 1 48 java.net.SocketInputStream
150: 1 48 java.nio.HeapCharBuffer
151: 2 48 java.nio.charset.CoderResult
152: 3 48 java.nio.charset.CodingErrorAction
153: 3 48 java.util.Collections$UnmodifiableSet
154: 3 48 java.util.HashMap$KeySet
155: 2 48 sun.misc.JarIndex
156: 2 48 sun.misc.NativeSignalHandler
157: 2 48 sun.misc.Signal
158: 3 48 sun.net.www.protocol.jar.Handler
159: 1 48 sun.nio.cs.StreamDecoder
160: 1 48 sun.nio.cs.US_ASCII$Decoder
161: 1 48 sun.util.locale.provider.LocaleResources$ResourceReference
162: 1 48 sun.util.resources.TimeZoneNames
163: 1 48 sun.util.resources.en.TimeZoneNames_en
164: 1 40 [Lsun.util.locale.provider.LocaleProviderAdapter$Type;
165: 1 40 java.io.BufferedInputStream
166: 1 40 java.util.ResourceBundle$1
167: 1 40 sun.nio.cs.StandardCharsets$Aliases
168: 1 40 sun.nio.cs.StandardCharsets$Cache
169: 1 40 sun.nio.cs.StandardCharsets$Classes
170: 1 40 sun.nio.cs.ext.ExtendedCharsets
171: 1 32 [Ljava.lang.OutOfMemoryError;
172: 2 32 [Ljava.lang.StackTraceElement;
173: 1 32 [Ljava.lang.ThreadGroup;
174: 1 32 [Ljava.net.Proxy$Type;
175: 1 32 java.io.FileInputStream
176: 1 32 java.io.WinNTFileSystem
177: 1 32 java.lang.ArithmeticException
178: 2 32 java.lang.Boolean
179: 1 32 java.lang.NullPointerException
180: 1 32 java.net.InetAddress$InetAddressHolder
181: 1 32 java.net.Socket
182: 2 32 java.nio.ByteOrder
183: 2 32 java.util.LinkedHashMap$LinkedKeySet
184: 2 32 java.util.concurrent.atomic.AtomicInteger
185: 1 32 java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl
186: 1 32 jdk.net.ExtendedSocketOptions$1
187: 1 32 sun.instrument.InstrumentationImpl
188: 1 32 sun.nio.cs.StandardCharsets
189: 1 32 sun.util.locale.provider.LocaleResources
190: 1 32 sun.util.locale.provider.LocaleServiceProviderPool
191: 1 24 [Ljava.io.File$PathStatus;
192: 1 24 [Ljava.lang.ClassValue$Entry;
193: 1 24 [Ljava.net.InetAddress$Cache$Type;
194: 1 24 [Ljava.security.ProtectionDomain;
195: 1 24 [Lsun.launcher.LauncherHelper;
196: 1 24 java.io.InputStreamReader
197: 1 24 java.lang.ClassValue$Version
198: 1 24 java.lang.StringBuilder
199: 1 24 java.lang.invoke.MethodHandleImpl$4
200: 1 24 java.lang.reflect.ReflectPermission
201: 1 24 java.net.Inet4Address
202: 1 24 java.net.Inet6AddressImpl
203: 1 24 java.net.Proxy
204: 1 24 java.util.BitSet
205: 1 24 java.util.Collections$EmptyMap
206: 1 24 java.util.Collections$SetFromMap
207: 1 24 java.util.Collections$SynchronizedSet
208: 1 24 java.util.Locale$Cache
209: 1 24 java.util.ResourceBundle$Control$CandidateListCache
210: 1 24 java.util.concurrent.TimeUnit$1
211: 1 24 java.util.concurrent.TimeUnit$2
212: 1 24 java.util.concurrent.TimeUnit$3
213: 1 24 java.util.concurrent.TimeUnit$4
214: 1 24 java.util.concurrent.TimeUnit$5
215: 1 24 java.util.concurrent.TimeUnit$6
216: 1 24 java.util.concurrent.TimeUnit$7
217: 1 24 java.util.jar.Manifest
218: 1 24 sun.instrument.TransformerManager
219: 1 24 sun.launcher.LauncherHelper
220: 1 24 sun.misc.URLClassPath$FileLoader
221: 1 24 sun.nio.cs.ISO_8859_1
222: 1 24 sun.nio.cs.ThreadLocalCoders$1
223: 1 24 sun.nio.cs.ThreadLocalCoders$2
224: 1 24 sun.nio.cs.US_ASCII
225: 1 24 sun.nio.cs.UTF_16
226: 1 24 sun.nio.cs.UTF_16BE
227: 1 24 sun.nio.cs.UTF_16LE
228: 1 24 sun.nio.cs.UTF_8
229: 1 24 sun.nio.cs.ext.GBK
230: 1 24 sun.reflect.NativeMethodAccessorImpl
231: 1 24 sun.util.locale.BaseLocale$Cache
232: 1 24 sun.util.locale.provider.TimeZoneNameProviderImpl
233: 1 16 [Ljava.lang.Throwable;
234: 1 16 [Ljava.security.cert.Certificate;
235: 1 16 [Lsun.instrument.TransformerManager$TransformerInfo;
236: 1 16 java.io.FileDescriptor$1
237: 1 16 java.lang.CharacterDataLatin1
238: 1 16 java.lang.ClassValue$Identity
239: 1 16 java.lang.Runtime
240: 1 16 java.lang.String$CaseInsensitiveComparator
241: 1 16 java.lang.System$2
242: 1 16 java.lang.Terminator$1
243: 1 16 java.lang.invoke.MemberName$Factory
244: 1 16 java.lang.invoke.MethodHandleImpl$2
245: 1 16 java.lang.invoke.MethodHandleImpl$3
246: 1 16 java.lang.ref.Reference$1
247: 1 16 java.lang.ref.Reference$Lock
248: 1 16 java.lang.reflect.ReflectAccess
249: 1 16 java.net.InetAddress$2
250: 1 16 java.net.URLClassLoader$7
251: 1 16 java.nio.Bits$1
252: 1 16 java.nio.charset.CoderResult$1
253: 1 16 java.nio.charset.CoderResult$2
254: 1 16 java.security.ProtectionDomain$2
255: 1 16 java.security.ProtectionDomain$JavaSecurityAccessImpl
256: 1 16 java.util.Collections$EmptyIterator
257: 1 16 java.util.Collections$EmptyList
258: 1 16 java.util.Collections$EmptySet
259: 1 16 java.util.Hashtable$EntrySet
260: 1 16 java.util.ResourceBundle$Control
261: 1 16 java.util.WeakHashMap$KeySet
262: 1 16 java.util.concurrent.atomic.AtomicBoolean
263: 1 16 java.util.jar.Attributes
264: 1 16 java.util.jar.JavaUtilJarAccessImpl
265: 1 16 java.util.zip.ZipFile$1
266: 1 16 jdk.net.ExtendedSocketOptions$PlatformSocketOptions
267: 1 16 sun.misc.ASCIICaseInsensitiveComparator
268: 1 16 sun.misc.FloatingDecimal$1
269: 1 16 sun.misc.Launcher
270: 1 16 sun.misc.Launcher$Factory
271: 1 16 sun.misc.Perf
272: 1 16 sun.misc.Unsafe
273: 1 16 sun.net.spi.DefaultProxySelector
274: 1 16 sun.net.www.protocol.file.Handler
275: 1 16 sun.reflect.DelegatingMethodAccessorImpl
276: 1 16 sun.reflect.ReflectionFactory
277: 1 16 sun.util.calendar.Gregorian
278: 1 16 sun.util.locale.provider.AuxLocaleProviderAdapter$NullProvider
279: 1 16 sun.util.locale.provider.SPILocaleProviderAdapter
280: 1 16 sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter
281: 1 16 sun.util.resources.LocaleData
282: 1 16 sun.util.resources.LocaleData$LocaleDataResourceBundleControl
Total 18064 32910960
四、其它作用
jmap -permstat 15144:查看系统的ClassLoader信息;
jmap -finalizerinfo 15144:查看堆积在finalizer队列中的对象;
注意,上述两个参数仅在linux/solaris平台有效。
五、小结
由于jmap将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap需要借助安全点机制,让所有线程停留在不改变堆中数据的状态。也就是说,由jmap导出的堆快照必定是安全点位置的,这可能导致基于该堆快照的分析结果存在偏差。
举个例子,假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么:live选项将无法探知到这些对象。
另外,如果某个线程长时间无法跑到安全点,jmap将一直等下去。与前面讲的jstat则不同,垃圾回收器会主动将jstat所需要的摘要数据保存至固定位置,只需直接读取即可。