一、基本情况
jmap(JVM Memory Map):作用一方面是获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。
开发人员可以在控制台中输入命令“jmap -help”查阅jmap工具的具体使用方式和一些标准选项配置。
官方帮助文档:
https://docs.oracle.com/en/java/javase/11/tools/jmap.html
二、基本语法
它的基本使用语法为:
- jmap [option]
- jmap [option]
- jmap [option] [server_id@]
其中option包括:
说明:这些参数和linux下输入显示的命令多少会有不同,包括也受jdk版本的影响。
2.1、-dump
生成Java堆转储快照: dump文件
特别的: -dump:live只保存堆中的存活对象
可以从dump文件中分析出那些对象导致了堆或非堆的溢出
2.2、-heap
输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等
2.3、-histo
输出堆中对象的统计信息,包括类、实例数量和合计容量
特别的: -histo:live只统计堆中的存活对象
2.4、-permstat
以ClassLoader为统计口径输出永久代的内存状态信息
仅linux/solaris平台有效
2.5、-finalizerinfo
显示在F-Queue中等待Finalizer线程执行finalize方法的对象
仅linux/solaris平台有效
2.6、-F
当虚拟机进程对-dump选项没有任何响应时,可使用此选项强制执行生成dump文件
仅linux/solaris平台有效
2.7、-h | -help
2.8、-J
三、使用1:导出内存映像文件
一般来说,使用jmap指令生成dump文件的操作算得上是最常用的jmap命令之一,将堆中所有存活对象导出至一个文件之中。
Heap Dump又叫做堆存储文件,指一个Java进程在某个时间点的内存快照。Heap Dump在触发内存快照的时候会保存此刻的信息如下:
- All Objects
Class,fields,primitive values and references.
- All Classes
ClassLoader,name , super class,static fields
- Garbage Collection Roots
0bjects defined to be reachable by the JVM
- Thread Stacks and Local Variables
The call-stacks of threads at the moment of the snapshot,and per-frameinformation about local objects
说明:
1.通常在写Heap Dump文件前会触发一次Full Gc,所以heap dump文件里保存的都是Ful1GC后留下的对象信息。
2.由于生成dump文件比较耗时,因此大家需要耐心等待,尤其是大内存镜像生成dump文件则需要耗费更长的时间来完成。
3.1、手动的方式
jmap -dump:format=b,file=
jmap -dump:live,format=b,file=
其中format=b是将jmap生成的hprof文件能被图形界面工具识别
-dump:live打印存活的对象
jmap -dump:live,format=b,file=F:\weblogicdump\dump.hprof 9376
请使用JProfiler工具打开dump文件
3.2、自动的方式
当程序发生OOM退出系统时,一些瞬时信息都随着程序的终止而消失,而重现OOM问题往往比较困难或者耗时。此时若能在OOM时,自动导出dump文件就显得非常迫切。
这里介绍一种比较常用的取得堆快照文件的方法,即使用:
-XX:+HeapDumpOnOutOfMemoryError: 在程序发生OOM时,导出应用程序的当前堆快照。
-XX:HeapDumpPath: 可以指定堆快照的保存位置。
比如:
-Xmx100m -XX:+HeapDumpOnOutOfMemoryError -XX:+HeapDumpPath=D:\dump\m.hprof
指令:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=
-Xms60m -Xmx60m -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=dump5.hprof
四、使用2:显示堆内存相关信息
4.1、jmap -heap pid
a.txt文件内容如下:
Attaching to process ID 3076, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.291-b10
using thread-local object allocation.
Parallel GC with 8 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 = 16777216 (16.0MB)
used = 7799040 (7.437744140625MB)
free = 8978176 (8.562255859375MB)
46.48590087890625% used
From Space:
capacity = 2097152 (2.0MB)
used = 2076896 (1.980682373046875MB)
free = 20256 (0.019317626953125MB)
99.03411865234375% used
To Space:
capacity = 2097152 (2.0MB)
used = 0 (0.0MB)
free = 2097152 (2.0MB)
0.0% used
PS Old Generation
capacity = 41943040 (40.0MB)
used = 11857992 (11.308662414550781MB)
free = 30085048 (28.69133758544922MB)
28.271656036376953% used
3174 interned Strings occupying 260464 bytes.
4.2、-jmap -histo pid
b.txt文件内容如下:
num #instances #bytes class name
----------------------------------------------
1: 1037 55953232 [B
2: 5047 512872 [C
3: 4898 117552 java.lang.String
4: 706 80880 java.lang.Class
5: 708 50864 [Ljava.lang.Object;
6: 791 31640 java.util.TreeMap$Entry
7: 136 21400 [I
8: 239 15296 java.net.URL
9: 470 15040 java.util.HashMap$Node
10: 267 12640 [Ljava.lang.String;
11: 79 7584 java.util.jar.JarFile$JarFileEntry
12: 91 7280 [Ljava.util.WeakHashMap$Entry;
13: 170 6800 java.lang.ref.Finalizer
14: 118 6608 sun.misc.URLClassPath$JarLoader
15: 28 6464 [Ljava.util.HashMap$Node;
16: 88 5632 java.util.jar.JarFile
17: 90 5040 sun.nio.cs.UTF_8$Encoder
18: 120 4800 java.util.LinkedHashMap$Entry
19: 110 4400 java.lang.ref.SoftReference
20: 91 4368 java.util.WeakHashMap
21: 256 4096 java.lang.Integer
22: 121 3872 java.util.Hashtable$Entry
23: 73 3504 java.util.zip.Inflater
24: 106 3392 java.util.concurrent.ConcurrentHashMap$Node
25: 84 3360 sun.nio.cs.UTF_8$Decoder
26: 98 3136 java.lang.ref.ReferenceQueue
27: 8 3008 java.lang.Thread
28: 120 2880 java.io.ExpiringCache$Entry
29: 88 2816 java.util.zip.ZipCoder
30: 88 2112 java.util.ArrayDeque
31: 26 2080 java.lang.reflect.Constructor
32: 15 1968 [Ljava.util.concurrent.ConcurrentHashMap$Node;
33: 39 1872 sun.util.locale.LocaleObjectCache$CacheEntry
34: 38 1824 java.util.HashMap
35: 73 1752 java.util.zip.ZStreamRef
36: 100 1600 java.lang.ref.ReferenceQueue$Lock
37: 1 1568 [[B
38: 37 1480 java.io.ObjectStreamField
39: 85 1360 java.lang.Object
40: 19 1216 java.util.concurrent.ConcurrentHashMap
41: 9 1184 [Ljava.util.Hashtable$Entry;
42: 48 1152 java.util.LinkedList$Node
43: 2 1064 [Ljava.lang.invoke.MethodHandle;
44: 1 1040 [Ljava.lang.Integer;
45: 1 1040 [[C
46: 28 896 java.util.LinkedList
47: 19 760 sun.util.locale.BaseLocale$Key
48: 8 640 [S
49: 19 608 java.io.File
50: 19 608 java.util.Locale
51: 19 608 sun.util.locale.BaseLocale
52: 13 520 java.security.AccessControlContext
53: 19 456 java.util.Locale$LocaleKey
54: 18 432 sun.misc.MetaIndex
55: 17 408 java.util.jar.Attributes$Name
56: 13 392 [Ljava.io.ObjectStreamField;
57: 1 384 com.intellij.rt.execution.application.AppMainV2$1
58: 1 384 java.lang.ref.Finalizer$FinalizerThread
59: 6 384 java.nio.DirectByteBuffer
60: 1 376 java.lang.ref.Reference$ReferenceHandler
61: 6 336 java.nio.DirectLongBufferU
62: 10 320 java.lang.OutOfMemoryError
63: 3 312 [D
64: 2 312 [J
65: 13 312 sun.reflect.NativeConstructorAccessorImpl
66: 12 288 java.util.ArrayList
67: 15 280 [Ljava.lang.Class;
68: 5 280 sun.util.calendar.ZoneInfo
69: 11 264 java.net.StandardSocketOptions$StdSocketOption
70: 8 256 java.util.Vector
71: 3 240 [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;
72: 5 240 java.util.Hashtable
73: 13 208 sun.reflect.DelegatingConstructorAccessorImpl
74: 5 200 java.security.ProtectionDomain
75: 5 200 java.util.WeakHashMap$Entry
76: 6 192 java.lang.ThreadLocal$ThreadLocalMap$Entry
77: 4 192 java.util.Properties
78: 4 192 java.util.TreeMap
79: 2 160 [[Ljava.lang.String;
80: 4 160 java.io.FileDescriptor
81: 4 160 java.lang.ClassLoader$NativeLibrary
82: 5 160 java.security.CodeSource
83: 5 160 sun.util.locale.provider.LocaleProviderAdapter$Type
84: 3 144 java.nio.HeapByteBuffer
85: 6 144 sun.misc.PerfCounter
86: 3 144 sun.misc.URLClassPath
87: 2 128 java.io.ExpiringCache$1
88: 4 128 java.util.Stack
89: 1 120 java.net.SocksSocketImpl
90: 5 120 java.util.Collections$UnmodifiableRandomAccessList
91: 5 120 sun.misc.FloatingDecimal$PreparedASCIIToBinaryBuffer
92: 2 112 java.lang.Package
93: 7 112 java.util.HashSet
94: 2 112 java.util.LinkedHashMap
95: 2 112 java.util.ResourceBundle$CacheKey
96: 4 96 java.lang.RuntimePermission
97: 2 96 java.lang.ThreadGroup
98: 6 96 java.lang.ThreadLocal
99: 1 96 java.net.DualStackPlainSocketImpl
100: 2 96 java.util.ResourceBundle$BundleReference
101: 4 96 jdk.net.ExtendedSocketOptions$ExtSocketOption
102: 4 96 sun.misc.JarIndex
103: 1 96 sun.misc.Launcher$AppClassLoader
104: 3 96 sun.net.spi.DefaultProxySelector$NonProxyInfo
105: 2 96 sun.nio.cs.StreamEncoder
106: 1 88 sun.misc.Launcher$ExtClassLoader
107: 5 80 [Ljava.security.Principal;
108: 2 80 java.io.BufferedWriter
109: 2 80 java.io.ExpiringCache
110: 5 80 java.security.ProtectionDomain$Key
111: 2 80 sun.misc.FloatingDecimal$BinaryToASCIIBuffer
112: 3 72 java.lang.ThreadLocal$ThreadLocalMap
113: 3 72 java.net.Proxy$Type
114: 3 72 java.util.Arrays$ArrayList
115: 1 72 java.util.ResourceBundle$RBClassLoader
116: 3 72 java.util.concurrent.atomic.AtomicLong
117: 3 72 sun.misc.FloatingDecimal$ExceptionalBinaryToASCIIBuffer
118: 1 72 sun.util.locale.provider.JRELocaleProviderAdapter
119: 1 64 [F
120: 2 64 [Ljava.lang.Thread;
121: 2 64 java.io.FileOutputStream
122: 2 64 java.io.FilePermission
123: 2 64 java.io.PrintStream
124: 2 64 java.lang.ClassValue$Entry
125: 2 64 java.lang.VirtualMachineError
126: 2 64 java.lang.ref.ReferenceQueue$Null
127: 2 64 java.security.BasicPermissionCollection
128: 2 64 java.security.Permissions
129: 2 64 java.util.ResourceBundle$LoaderReference
130: 2 48 java.io.BufferedOutputStream
131: 1 48 java.io.BufferedReader
132: 2 48 java.io.File$PathStatus
133: 2 48 java.io.FilePermissionCollection
134: 2 48 java.io.OutputStreamWriter
135: 2 48 java.net.InetAddress$Cache
136: 2 48 java.net.InetAddress$Cache$Type
137: 1 48 java.net.SocketInputStream
138: 1 48 java.nio.HeapCharBuffer
139: 2 48 java.nio.charset.CoderResult
140: 3 48 java.nio.charset.CodingErrorAction
141: 3 48 java.util.Collections$UnmodifiableSet
142: 3 48 java.util.HashMap$KeySet
143: 2 48 sun.misc.NativeSignalHandler
144: 2 48 sun.misc.Signal
145: 3 48 sun.net.www.protocol.jar.Handler
146: 1 48 sun.nio.cs.StreamDecoder
147: 1 48 sun.nio.cs.US_ASCII$Decoder
148: 1 48 sun.util.locale.provider.LocaleResources$ResourceReference
149: 1 40 [Lsun.util.locale.provider.LocaleProviderAdapter$Type;
150: 1 40 java.io.BufferedInputStream
151: 1 40 java.util.ResourceBundle$1
152: 1 40 sun.nio.cs.StandardCharsets$Aliases
153: 1 40 sun.nio.cs.StandardCharsets$Cache
154: 1 40 sun.nio.cs.StandardCharsets$Classes
155: 1 40 sun.nio.cs.ext.ExtendedCharsets
156: 1 32 [Ljava.lang.OutOfMemoryError;
157: 2 32 [Ljava.lang.StackTraceElement;
158: 1 32 [Ljava.lang.ThreadGroup;
159: 1 32 [Ljava.net.Proxy$Type;
160: 1 32 java.io.FileInputStream
161: 1 32 java.io.WinNTFileSystem
162: 1 32 java.lang.ArithmeticException
163: 2 32 java.lang.Boolean
164: 1 32 java.lang.NullPointerException
165: 1 32 java.net.InetAddress$InetAddressHolder
166: 1 32 java.net.Socket
167: 2 32 java.nio.ByteOrder
168: 2 32 java.util.concurrent.atomic.AtomicInteger
169: 1 32 java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl
170: 1 32 jdk.net.ExtendedSocketOptions$1
171: 1 32 sun.instrument.InstrumentationImpl
172: 1 32 sun.nio.cs.StandardCharsets
173: 1 32 sun.util.locale.provider.LocaleResources
174: 1 32 sun.util.locale.provider.LocaleServiceProviderPool
175: 1 24 [Ljava.io.File$PathStatus;
176: 1 24 [Ljava.lang.ClassValue$Entry;
177: 1 24 [Ljava.net.InetAddress$Cache$Type;
178: 1 24 [Ljava.security.ProtectionDomain;
179: 1 24 [Lsun.launcher.LauncherHelper;
180: 1 24 java.io.InputStreamReader
181: 1 24 java.lang.ClassValue$Version
182: 1 24 java.lang.StringBuilder
183: 1 24 java.lang.invoke.MethodHandleImpl$4
184: 1 24 java.lang.reflect.ReflectPermission
185: 1 24 java.net.Inet4Address
186: 1 24 java.net.Inet6AddressImpl
187: 1 24 java.net.Proxy
188: 1 24 java.util.BitSet
189: 1 24 java.util.Collections$EmptyMap
190: 1 24 java.util.Collections$SetFromMap
191: 1 24 java.util.Collections$SynchronizedSet
192: 1 24 java.util.Locale$Cache
193: 1 24 java.util.ResourceBundle$Control$CandidateListCache
194: 1 24 sun.instrument.TransformerManager
195: 1 24 sun.launcher.LauncherHelper
196: 1 24 sun.misc.URLClassPath$FileLoader
197: 1 24 sun.nio.cs.ISO_8859_1
198: 1 24 sun.nio.cs.ThreadLocalCoders$1
199: 1 24 sun.nio.cs.ThreadLocalCoders$2
200: 1 24 sun.nio.cs.US_ASCII
201: 1 24 sun.nio.cs.UTF_16
202: 1 24 sun.nio.cs.UTF_16BE
203: 1 24 sun.nio.cs.UTF_16LE
204: 1 24 sun.nio.cs.UTF_8
205: 1 24 sun.util.locale.BaseLocale$Cache
206: 1 24 sun.util.locale.provider.TimeZoneNameProviderImpl
207: 1 16 [Ljava.lang.Throwable;
208: 1 16 [Ljava.security.cert.Certificate;
209: 1 16 [Lsun.instrument.TransformerManager$TransformerInfo;
210: 1 16 java.io.FileDescriptor$1
211: 1 16 java.lang.CharacterDataLatin1
212: 1 16 java.lang.ClassValue$Identity
213: 1 16 java.lang.Runtime
214: 1 16 java.lang.String$CaseInsensitiveComparator
215: 1 16 java.lang.System$2
216: 1 16 java.lang.Terminator$1
217: 1 16 java.lang.invoke.MemberName$Factory
218: 1 16 java.lang.invoke.MethodHandleImpl$2
219: 1 16 java.lang.invoke.MethodHandleImpl$3
220: 1 16 java.lang.ref.Reference$1
221: 1 16 java.lang.ref.Reference$Lock
222: 1 16 java.lang.reflect.ReflectAccess
223: 1 16 java.net.InetAddress$2
224: 1 16 java.net.URLClassLoader$7
225: 1 16 java.nio.Bits$1
226: 1 16 java.nio.charset.CoderResult$1
227: 1 16 java.nio.charset.CoderResult$2
228: 1 16 java.security.ProtectionDomain$2
229: 1 16 java.security.ProtectionDomain$JavaSecurityAccessImpl
230: 1 16 java.util.Collections$EmptyIterator
231: 1 16 java.util.Collections$EmptyList
232: 1 16 java.util.Collections$EmptySet
233: 1 16 java.util.Hashtable$EntrySet
234: 1 16 java.util.ResourceBundle$Control
235: 1 16 java.util.WeakHashMap$KeySet
236: 1 16 java.util.concurrent.atomic.AtomicBoolean
237: 1 16 java.util.jar.JavaUtilJarAccessImpl
238: 1 16 java.util.zip.ZipFile$1
239: 1 16 jdk.net.ExtendedSocketOptions$PlatformSocketOptions
240: 1 16 sun.misc.ASCIICaseInsensitiveComparator
241: 1 16 sun.misc.FloatingDecimal$1
242: 1 16 sun.misc.Launcher
243: 1 16 sun.misc.Launcher$Factory
244: 1 16 sun.misc.Perf
245: 1 16 sun.misc.Unsafe
246: 1 16 sun.net.spi.DefaultProxySelector
247: 1 16 sun.net.www.protocol.file.Handler
248: 1 16 sun.reflect.ReflectionFactory
249: 1 16 sun.util.calendar.Gregorian
250: 1 16 sun.util.locale.provider.AuxLocaleProviderAdapter$NullProvider
251: 1 16 sun.util.locale.provider.SPILocaleProviderAdapter
252: 1 16 sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter
253: 1 16 sun.util.resources.LocaleData
254: 1 16 sun.util.resources.LocaleData$LocaleDataResourceBundleControl
Total 17443 56945536
五、使用3:其它使用
5.1、jmap -permstat pid
5.2、jmap -finalizerinfo
六、小结
由于jmap将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap需要借助安全点机制,让所有线程停留在不改变堆中数据的状态。也就是说,由jmap导出的堆快照必定是安全点位置的。这可能导致基于该堆快照的分析结果存在偏差。
举个例子,假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么: live选项将无法探知到这些对象。
另外,如果某个线程长时间无法跑到安全点,jmap将一直等下去。与前面讲的jstat则不同,垃圾回收器会主动将jstat所需要的摘要数据保存至固定位置之中,而jstat只需直接读取即可。