赞
踩
jmap(JVM Memory Map):作用一方面是获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。开发人员可以在控制台中输入命令“jmap -help”查阅jmap工具的具体使用方式和一些标准选项配置。
他的不同的功能都是通过-option这个参数的不同来区分指定的。
官方帮助文档:https://docs.oracle.com/en/java/javase/11/tools/jmap.html
基本使用语法为:
● jmap [option] pid
● jmap [option] executable core
● jmap [option] [server_id@] remote server IP or hostname
导出的dump文件可以显示当前的jvm空间的对象分布情况,可以帮助我们分析这类关于对象文件的一个情况。
说明:这些参数和linux下输入显示的命令多少会有不同,包括也受jdk版本的影响。
导出dump文件是jmap最重要的作用之一,Heap Dump称之为堆存储文件,指的是一个java进程在某个时间点的内存对象的快照,那一瞬间的捕捉。Heap Dump在触发内存快照的时候会保存的此刻的信息如下。
1、全部的对象
2、全部的类信息
3、gc roots的信息
4、线程栈和本地变量的数据
以上四种数据会被那一瞬间捕捉到。
说明一下:、
1、通常在写Heap Dump文件前会触发一个full GC,所以heap dump里面保存的都是full gc后留下的对象的信息。
2、由于生产dump文件比较耗时,因此需要耐心等待,尤其是大内存的时候镜像生成dump文件需要耗费更长的时间完成。
语法
> jmap -dump:format=b,file=<filename.hprof> <pid>
> jmap -dump:live,format=b,file=<filename.hprof> <pid>
开一个程序
/** * @author: levi * @description: -Xms60m -Xmx60m -XX:SurvivorRatio=8 堆空间初始和最大值设置为60m,s区和eden区的比例为8:1:1 * @date: 2022-10-3 20:10 * @version: 1.0 */ public class GCtest { // 100KB大小 static final int _100KB = 1024 * 100; public static void main(String[] args) { List<byte[]> list = new ArrayList<>(); for (int i = 0; i < 1000; i++) { // 每120毫秒就添加100KB进这个集合里面 byte[] arr = new byte[_100KB]; list.add(arr); try { Thread.sleep(120); } catch (InterruptedException e) { e.printStackTrace(); } } } }
查看jps找到线程id为136888
我们使用jmap来操作生成一下dump文件。
# 我们连续导出两个dump文件
jmap -dump:format=b,file=D:1.hprof 136888
Dumping heap to D:\1.hprof ...
Heap dump file created
jmap -dump:format=b,file=D:2.hprof 136888
Dumping heap to D:\2.hprof ...
Heap dump file created
# 然后使用live标签导出一个名字为3的dump文件
jmap -dump:live,format=b,file=D:3.hprof 136888
Dumping heap to D:\3.hprof ...
Heap dump file created
我们来解释一下这个命令
jmap -dump:format=b,file=D:1.hprof 136888
-dump表示就是导出堆文件的参数。
format=b.file表示我们导出这个文件的格式是标准格式,后面能用那些工具打开。
file=D:1.hprof 表示导出位置在D盘下面,名字为1,格式是hprof。
136888就是这个程序的进程id。
jmap -dump:live,format=b,file=D:3.hprof 136888
其余的一样,就是加了一个live标签,表示我们导出的是当前快照里面只有存活对象,回收的不导出了。上面那种是整个堆都导出,包括回收的和存活的对象。
有时候我们生产使用的时候,一般有存活的就行了,因为已经回收的不影响了,有问题都是那些没法回收的对象导致的。这样只导出存活的文件大小还能小点。
此时你每次执行这个命令都能导出对应的文件了。
但是这个hprof文件是二进制的,你得用工具看。文本打开看的就是乱码。
由于jmap将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap需要借助安全点机制,让所有线程停留在不改变堆中数据的状态。也就是说,由jmap导出的堆快照必定是安全点位置的。这可能导致基于该堆快照的分析结果存在偏差。
举个例子,假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么:live选项将无法探知到这些对象。
另外,如果某个线程长时间无法跑到安全点,jmap将一直等下去。与前面讲的jstat则不同,垃圾回收器会主动将jstat所需要的摘要数据保存至固定位置之中,而jstat只需直接读取即可。
自动导出的意思就是你不用管,只要你配置好参数,等到他堆溢出了,自己会按照你得配置生成指定的文件。
只需要我们配置两个东西
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=d:\\5.hprof
第一个就是配置堆内存溢出的时候自动导出,第二行就是配置自动导出时候的hprof文件的位置。
等到溢出了就会生成该文件。
配置参数为: -Xms60m -Xmx60m -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:\\5.hprof public class GCtest { // 100KB大小 static final int _100KB = 1024 * 100; public static void main(String[] args) { List<byte[]> list = new ArrayList<>(); for (int i = 0; i < 1000; i++) { // 每120毫秒就添加100KB进这个集合里面 byte[] arr = new byte[_100KB]; list.add(arr); try { Thread.sleep(6); } catch (InterruptedException e) { e.printStackTrace(); } } } }
等到溢出的时候我们看一下D盘:
我们先运行那段程序,然后jps查看出线程id为8960.
我们执行jmap -heap 8960 > d:1.txt
jmap -histo 8960 > d:2.txt
我们为了方便查看把结果导出到txt文件里面。
我们程序运行的jvm参数为:-Xms60m -Xmx60m -XX:SurvivorRatio=8
我们查看一下-heap的结果为:
Attaching to process ID 8836, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.181-b13 using thread-local object allocation. Parallel GC with 8 thread(s) # 下面就是堆内存大小的显式,和我们在jvm参数中配置的是一样的。 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) # 下面是我导出那一瞬间的时候当前的jvm内存里面的占用情况 Heap Usage: PS Young Generation Eden Space: capacity = 16777216 (16.0MB) used = 6128432 (5.8445281982421875MB) free = 10648784 (10.155471801757812MB) 36.52830123901367% used From Space: capacity = 2097152 (2.0MB) used = 0 (0.0MB) free = 2097152 (2.0MB) 0.0% 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 = 31067936 (29.628692626953125MB) free = 10875104 (10.371307373046875MB) 74.07173156738281% used 1734 interned Strings occupying 156752 bytes.
我们查看一下-histo的结果为:
下面我们看到的他是你当前导出那一瞬间的空间的占用情况,比如类名,对象实例的大小,按从大到小排列的,我们可以据此查看一下空间里面有哪些大对象。
num #instances #bytes class name ---------------------------------------------- 1: 358 33413272 [B 2: 2518 329744 [C 3: 603 69048 java.lang.Class 4: 2373 56952 java.lang.String 5: 605 36296 [Ljava.lang.Object; 6: 791 31640 java.util.TreeMap$Entry 7: 115 25032 [I 8: 197 8056 [Ljava.lang.String; 9: 79 5688 java.lang.reflect.Field 10: 85 5440 java.net.URL 11: 152 4864 java.util.Hashtable$Entry 12: 137 4384 java.util.concurrent.ConcurrentHashMap$Node 13: 11 4136 java.lang.Thread 14: 256 4096 java.lang.Integer 15: 99 3960 java.lang.ref.SoftReference 16: 100 3200 java.util.HashMap$Node 17: 42 2352 sun.misc.URLClassPath$JarLoader 18: 19 1968 [Ljava.util.HashMap$Node; 19: 123 1968 java.lang.Object 20: 46 1840 java.util.LinkedHashMap$Entry 21: 38 1824 sun.util.locale.LocaleObjectCache$CacheEntry 22: 21 1680 [Ljava.util.WeakHashMap$Entry; 23: 18 1440 java.lang.reflect.Constructor 24: 5 1424 [Ljava.util.concurrent.ConcurrentHashMap$Node; 25: 16 1408 java.lang.reflect.Method 26: 8 1264 [Ljava.util.Hashtable$Entry; 27: 13 1248 java.util.jar.JarFile$JarFileEntry 28: 31 1240 java.lang.ref.Finalizer 29: 25 1200 java.util.HashMap 30: 21 1176 sun.nio.cs.UTF_8$Encoder 31: 18 1152 java.util.jar.JarFile 32: 46 1104 java.io.ExpiringCache$Entry 33: 2 1064 [Ljava.lang.invoke.MethodHandle; 34: 19 1064 java.lang.Class$ReflectionData 35: 1 1040 [Ljava.lang.Integer; 36: 1 1040 [[C 37: 26 1040 java.io.ObjectStreamField 38: 21 1008 java.util.WeakHashMap 39: 27 864 com.intellij.rt.debugger.agent.CaptureAgent$InstrumentPoint 40: 26 832 java.lang.ref.ReferenceQueue 41: 19 760 sun.util.locale.BaseLocale$Key 42: 29 696 java.util.ArrayList 43: 8 640 [S 44: 19 608 java.util.Locale 45: 19 608 sun.util.locale.BaseLocale 46: 15 600 java.security.AccessControlContext 47: 15 600 sun.nio.cs.UTF_8$Decoder 48: 27 584 [Ljava.lang.Class; 49: 18 576 java.util.zip.ZipCoder 50: 8 512 java.util.concurrent.ConcurrentHashMap 51: 20 480 java.util.jar.Attributes$Name 52: 8 456 [Ljava.lang.reflect.Field; 53: 19 456 java.util.Locale$LocaleKey 54: 28 448 java.lang.ref.ReferenceQueue$Lock 55: 18 432 java.util.ArrayDeque 56: 13 416 java.io.File 57: 1 384 java.lang.ref.Finalizer$FinalizerThread 58: 6 384 java.nio.DirectByteBuffer 59: 8 384 java.util.zip.Inflater 60: 1 376 java.lang.ref.Reference$ReferenceHandler 61: 6 336 java.nio.DirectLongBufferU 62: 10 320 java.lang.OutOfMemoryError 63: 10 288 [Ljava.io.ObjectStreamField; 64: 12 288 sun.misc.MetaIndex 65: 6 240 java.util.WeakHashMap$Entry 66: 9 216 [Ljava.lang.reflect.Constructor; 67: 9 216 sun.reflect.NativeConstructorAccessorImpl 68: 4 192 java.util.Hashtable 69: 4 192 java.util.Properties 70: 4 192 java.util.TreeMap 71: 6 192 java.util.Vector 72: 8 192 java.util.zip.ZStreamRef 73: 3 168 java.lang.Package 74: 4 160 java.security.ProtectionDomain 75: 6 144 java.util.LinkedList$Node 76: 2 144 java.util.regex.Pattern 77: 6 144 sun.misc.PerfCounter 78: 9 144 sun.reflect.DelegatingConstructorAccessorImpl 79: 6 144 sun.security.util.DisabledAlgorithmConstraints$Constraint$Operator 80: 2 128 java.io.ExpiringCache$1 81: 4 128 java.security.CodeSource 82: 4 128 java.util.LinkedList 83: 3 120 java.io.FileDescriptor 84: 2 96 [Ljava.lang.reflect.Method; 85: 4 96 java.lang.RuntimePermission 86: 2 96 java.lang.ThreadGroup 87: 3 96 java.lang.ThreadLocal$ThreadLocalMap$Entry 88: 2 96 java.nio.HeapByteBuffer 89: 3 96 java.nio.file.attribute.FileTime 90: 3 96 java.util.Stack 91: 1 96 sun.misc.Launcher$AppClassLoader 92: 2 96 sun.misc.URLClassPath 93: 2 96 sun.nio.cs.StreamEncoder 94: 1 88 sun.misc.Launcher$ExtClassLoader 95: 1 80 [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry; 96: 2 80 java.io.BufferedWriter 97: 2 80 java.io.ExpiringCache 98: 2 80 java.lang.ClassLoader$NativeLibrary 99: 5 80 java.lang.ThreadLocal 100: 2 80 sun.security.util.DisabledAlgorithmConstraints$KeySizeConstraint 101: 3 72 java.util.Collections$SynchronizedSet 102: 3 72 java.util.concurrent.atomic.AtomicLong 103: 2 64 [Ljava.lang.Thread; 104: 4 64 [Ljava.security.Principal; 105: 2 64 java.io.FileOutputStream 106: 2 64 java.io.FilePermission 107: 2 64 java.io.PrintStream 108: 2 64 java.lang.ClassValue$Entry 109: 2 64 java.lang.VirtualMachineError 110: 2 64 java.lang.ref.ReferenceQueue$Null 111: 2 64 java.security.BasicPermissionCollection 112: 2 64 java.security.Permissions 113: 4 64 java.security.ProtectionDomain$Key 114: 1 56 sun.nio.cs.ext.DoubleByte$Decoder 115: 1 48 [J 116: 1 48 [Ljava.util.concurrent.TimeUnit; 117: 2 48 java.io.BufferedOutputStream 118: 2 48 java.io.File$PathStatus 119: 2 48 java.io.FilePermissionCollection 120: 2 48 java.io.OutputStreamWriter 121: 2 48 java.nio.charset.CoderResult 122: 3 48 java.nio.charset.CodingErrorAction 123: 2 48 java.util.regex.Pattern$SliceI 124: 2 48 java.util.regex.Pattern$Start 125: 2 48 sun.instrument.TransformerManager 126: 2 48 sun.misc.NativeSignalHandler 127: 2 48 sun.misc.Signal 128: 2 48 sun.security.util.DisabledAlgorithmConstraints$DisabledConstraint 129: 2 40 [Lsun.instrument.TransformerManager$TransformerInfo; 130: 1 40 [Lsun.security.util.DisabledAlgorithmConstraints$Constraint$Operator; 131: 1 40 java.io.BufferedInputStream 132: 1 40 sun.nio.cs.StandardCharsets$Aliases 133: 1 40 sun.nio.cs.StandardCharsets$Cache 134: 1 40 sun.nio.cs.StandardCharsets$Classes 135: 1 40 sun.nio.cs.ext.ExtendedCharsets 136: 1 32 [Ljava.lang.OutOfMemoryError; 137: 2 32 [Ljava.lang.StackTraceElement; 138: 1 32 [Ljava.lang.ThreadGroup; 139: 2 32 com.intellij.rt.debugger.agent.CaptureAgent$ParamKeyProvider 140: 1 32 java.io.FileInputStream 141: 1 32 java.io.WinNTFileSystem 142: 1 32 java.lang.ArithmeticException 143: 2 32 java.lang.Boolean 144: 1 32 java.lang.NullPointerException 145: 1 32 java.lang.StringCoding$StringDecoder 146: 1 32 java.lang.StringCoding$StringEncoder 147: 2 32 java.nio.ByteOrder 148: 2 32 java.util.HashSet 149: 2 32 java.util.concurrent.atomic.AtomicInteger 150: 1 32 java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl 151: 1 32 java.util.regex.Pattern$Branch 152: 1 32 sun.instrument.InstrumentationImpl 153: 2 32 sun.net.www.protocol.jar.Handler 154: 1 32 sun.nio.cs.StandardCharsets 155: 1 24 [Ljava.io.File$PathStatus; 156: 1 24 [Ljava.lang.ClassValue$Entry; 157: 1 24 [Ljava.util.regex.Pattern$Node; 158: 1 24 [Lsun.launcher.LauncherHelper; 159: 1 24 com.intellij.rt.debugger.agent.CaptureAgent$FieldKeyProvider 160: 1 24 java.lang.ClassValue$Version 161: 1 24 java.lang.StringBuilder 162: 1 24 java.lang.ThreadLocal$ThreadLocalMap 163: 1 24 java.lang.invoke.MethodHandleImpl$4 164: 1 24 java.lang.reflect.ReflectPermission 165: 1 24 java.util.BitSet 166: 1 24 java.util.Collections$EmptyMap 167: 1 24 java.util.Collections$SetFromMap 168: 1 24 java.util.Collections$UnmodifiableRandomAccessList 169: 1 24 java.util.Locale$Cache 170: 1 24 java.util.concurrent.TimeUnit$1 171: 1 24 java.util.concurrent.TimeUnit$2 172: 1 24 java.util.concurrent.TimeUnit$3 173: 1 24 java.util.concurrent.TimeUnit$4 174: 1 24 java.util.concurrent.TimeUnit$5 175: 1 24 java.util.concurrent.TimeUnit$6 176: 1 24 java.util.concurrent.TimeUnit$7 177: 1 24 java.util.jar.Manifest 178: 1 24 java.util.regex.Pattern$Single 179: 1 24 sun.instrument.TransformerManager$TransformerInfo 180: 1 24 sun.launcher.LauncherHelper 181: 1 24 sun.misc.JarIndex 182: 1 24 sun.misc.URLClassPath$FileLoader 183: 1 24 sun.nio.cs.ISO_8859_1 184: 1 24 sun.nio.cs.ThreadLocalCoders$1 185: 1 24 sun.nio.cs.ThreadLocalCoders$2 186: 1 24 sun.nio.cs.US_ASCII 187: 1 24 sun.nio.cs.UTF_16 188: 1 24 sun.nio.cs.UTF_16BE 189: 1 24 sun.nio.cs.UTF_16LE 190: 1 24 sun.nio.cs.UTF_8 191: 1 24 sun.nio.cs.ext.GBK 192: 1 24 sun.reflect.NativeMethodAccessorImpl 193: 1 24 sun.security.util.DisabledAlgorithmConstraints 194: 1 24 sun.util.locale.BaseLocale$Cache 195: 1 16 [Ljava.lang.Throwable; 196: 1 16 [Ljava.security.cert.Certificate; 197: 1 16 com.intellij.rt.debugger.agent.CaptureAgent$1 198: 1 16 com.intellij.rt.debugger.agent.CaptureAgent$CaptureTransformer 199: 1 16 com.intellij.rt.debugger.agent.CaptureStorage$1 200: 1 16 java.io.FileDescriptor$1 201: 1 16 java.lang.CharacterDataLatin1 202: 1 16 java.lang.ClassValue$Identity 203: 1 16 java.lang.Runtime 204: 1 16 java.lang.String$CaseInsensitiveComparator 205: 1 16 java.lang.System$2 206: 1 16 java.lang.Terminator$1 207: 1 16 java.lang.invoke.MemberName$Factory 208: 1 16 java.lang.invoke.MethodHandleImpl$2 209: 1 16 java.lang.invoke.MethodHandleImpl$3 210: 1 16 java.lang.ref.Reference$1 211: 1 16 java.lang.ref.Reference$Lock 212: 1 16 java.lang.reflect.ReflectAccess 213: 1 16 java.net.URLClassLoader$7 214: 1 16 java.nio.Bits$1 215: 1 16 java.nio.charset.CoderResult$1 216: 1 16 java.nio.charset.CoderResult$2 217: 1 16 java.security.ProtectionDomain$2 218: 1 16 java.security.ProtectionDomain$JavaSecurityAccessImpl 219: 1 16 java.util.Collections$EmptyList 220: 1 16 java.util.Collections$EmptySet 221: 1 16 java.util.Hashtable$EntrySet 222: 1 16 java.util.WeakHashMap$KeySet 223: 1 16 java.util.concurrent.atomic.AtomicBoolean 224: 1 16 java.util.jar.Attributes 225: 1 16 java.util.jar.JavaUtilJarAccessImpl 226: 1 16 java.util.regex.Pattern$4 227: 1 16 java.util.regex.Pattern$BranchConn 228: 1 16 java.util.regex.Pattern$LastNode 229: 1 16 java.util.regex.Pattern$Node 230: 1 16 java.util.zip.ZipFile$1 231: 1 16 sun.misc.ASCIICaseInsensitiveComparator 232: 1 16 sun.misc.Launcher 233: 1 16 sun.misc.Launcher$Factory 234: 1 16 sun.misc.Perf 235: 1 16 sun.misc.Unsafe 236: 1 16 sun.net.www.protocol.file.Handler 237: 1 16 sun.reflect.DelegatingMethodAccessorImpl 238: 1 16 sun.reflect.ReflectionFactory 239: 1 16 sun.security.util.AlgorithmDecomposer 240: 1 16 sun.security.util.DisabledAlgorithmConstraints$Constraints Total 9747 34058552
但是我们上面说的jmap都是基于那一瞬间的值,不是连续的。这就是一个弊端。
jamp -permstat pid查看系统的ClassLoader的信息
jmap -finalizerinfo 查看堆积在finalizer队列中的对象。
这两个在win下面不能运行。需要在linux系统运行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。