我们一直在推动我们应用程序中的permgen内存空间越来越高,我试图找出我们是否有某种类型的泄漏进入permgen区域.我们不做热取消部署/重新部署操作,但我们有很多代理,包括动态和CGLIB生成.我们还做了一些复杂的类加载器位来支持各种用例,我怀疑这些也可能是导致permgen浪费的一个原因.
所以我在运行的应用程序上运行jmap -permstat,希望能够深入了解可能填补我们permgen空间的内容.(我还运行带有实时和死对象的正常堆转储,这样我就可以追溯可能来自permstat输出的线索).
但是,在jmap permstat列出的2400个类加载器中,除引导类加载器之外的所有类都被列为"死".这没有任何意义,因为该应用程序绝对是直播和工作.
我的理解是,如果有资格进行垃圾收集,jmap会将类加载器报告为"死"但我在这里肯定是错的......
我错过了什么?"死"在这里意味着什么?除了我在这里可能存在的误解之外,谷歌搜索并没有提供很多答案.
是否有任何工具可以查看JVM堆的不同代的对象统计信息?我正在研究潜在的内存泄漏,需要不同代的一些数据.我的用例是在旧代中拍摄对象的快照,等待,然后拍摄另一个快照进行比较.
JVisualVM提供了有关已创建对象的统计信息,但这对我没有多大帮助,因为我没有看到特定对象是否正在被提升或终身比它应该更快.
Jmap提供不同代的统计信息,但不提供基于对象的统计信息.在那个工具中,我只能看到老一代正在成长......
我正在尝试从WER在崩溃时采用的本机转储中提取Java堆转储:
jstack -m -l "c:\Program Files\Java\jre6\bin\java.exe" WER.tmp.hdmp
Run Code Online (Sandbox Code Playgroud)
但我得到以下异常:
Attaching to core c:\Users\xxx\Desktop\WER.tmp.hdmp from executable c:\Program Files\Java\jre6\bin\java.exe, please wait...
sun.jvm.hotspot.debugger.NoSuchSymbolException: Could not find symbol "gHotSpotVMTypes" in any of the known library names (jvm.dll, jvm_g.dll)
at sun.jvm.hotspot.HotSpotTypeDataBase.lookupInProcess(HotSpotTypeDataBase.java:389)
at sun.jvm.hotspot.HotSpotTypeDataBase.readVMTypes(HotSpotTypeDataBase.java:104)
at sun.jvm.hotspot.HotSpotTypeDataBase.<init>(HotSpotTypeDataBase.java:85)
at sun.jvm.hotspot.bugspot.BugSpotAgent.setupVM(BugSpotAgent.java:565)
at sun.jvm.hotspot.bugspot.BugSpotAgent.go(BugSpotAgent.java:494)
at sun.jvm.hotspot.bugspot.BugSpotAgent.attach(BugSpotAgent.java:348)
at sun.jvm.hotspot.tools.Tool.start(Tool.java:169)
at sun.jvm.hotspot.tools.JStack.main(JStack.java:86)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.tools.jstack.JStack.runJStackTool(JStack.java:118)
at sun.tools.jstack.JStack.main(JStack.java:84)
Debugger attached successfully.
jstack requires a java VM process/core!
Run Code Online (Sandbox Code Playgroud)
我仔细检查过:
如果我尝试使用jmap提取java堆转储,我会得到完全相同的错误.
有谁知道会出现什么问题?
使用工具jmap,可以创建两种格式的内存转储:
Binary format: jmap -dump:format=b,file=binary_dump.dat <pid>
Run Code Online (Sandbox Code Playgroud)
要么
Other format: jmap -dump:file=other_format_dump.dat <pid>
Run Code Online (Sandbox Code Playgroud)
我读过很多地方,例如jhat和jvisualvm等工具只能读取二进制格式。
所以:
我有一个使用其他格式创建的内存转储文件,需要能够对其进行检查,最好使用Eclipse Memory Analyzer Tool进行检查。
当我在jmap命令下运行时:
jmap -histo 14104
Run Code Online (Sandbox Code Playgroud)
我能够看到我的对象非常好的输出,有实例,使用的字节.
num #instances #bytes class name
----------------------------------------------
1: 1308333 398374280 [C
2: 55058 84410136 [B
3: 1548041 49537312 java.lang.ref.Finalizer
4: 1584594 38030256 java.util.HashMap$Entry
5: 1327543 31861032 java.lang.String
6: 765682 25734336 [Ljava.lang.Object;
Run Code Online (Sandbox Code Playgroud)
但遗憾的是,Oracle不支持此功能,并且最新的Windows和Linux JDK发行版中不提供此功能.有人可以帮助建议替代jmap吗?
用法)Jmap -heap [PID]
你好,我有 jmap 问题
我只想查看大小(-heap 选项)堆转储编号...
如果我运行 [jmap -heap PID] 运行 jvm 进程就会停止?
当使用 Jmap 的给定 Java 进程上发生 OutOfMemoryError 时,我一直尝试转储堆文件。
我已经能够转储堆文件,但我想将 HeapDumpOnOutOfMemoryError 标志添加到 Jmap,但我认为我做错了什么。难道我做错了什么?我试过了:
jmap -J-XX:+HeapDumpOnOutOfMemoryError -dump:live,file=/home/eduardo2/dumpfile.hprof 18763
Run Code Online (Sandbox Code Playgroud)
当我运行上面的代码时,它只显示以下内容 - 但它不会等待 OutOfMemoryError:
>> Dumping heap to /home/eduardo2/dump21file.hprof ...
>> Heap dump file created
Run Code Online (Sandbox Code Playgroud) jmap帮助显示:
...
Run Code Online (Sandbox Code Playgroud)-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....
一旦我转储了一个 Tomcat(使用 java param -Xmx384m)堆:
jmap -dump:file=dump.bin <pid>
Run Code Online (Sandbox Code Playgroud)
我得到了一个 ~300M 的转储文件。
当我只用活动对象转储它的堆时:
jmap -dump:live,file=live-dump.bin <pid>
Run Code Online (Sandbox Code Playgroud)
我得到了一个 ~120M 的转储文件。
我对活动对象的猜测可能是:
年轻代中的对象;
已使用/引用/可访问且不会被收集的对象。
哪一个是对的?
更新
我的猜测 #2 似乎是正确的,感谢 Alexey Ragozin 的解释(live选项将导致完整的 GC)。我按照他的提示再次测试:
jmap -dump:file=dump.hprof <pid>
jmap -dump:live,file=live-dump.hprof <pid>
jmap -dump:file=after-live-dump.hprof <pid>
Run Code Online (Sandbox Code Playgroud)
这 3 个文件的大小是:
dump.hprof ~190MB
live-dump.hprof …Run Code Online (Sandbox Code Playgroud) 正如标题状态,多少开销不jmap -histo和jmap -heap带来一个JVM分别?
如果内存敏感的Java进程处于边缘OutOfMemory(例如大约96%的堆已满,并且无法由完整的gc清除),那么其中一项操作可能会将jvm带到OutOfMemory吗?
我正在使用命令“jmap -histo pid”,想知道它到底告诉我什么。
输出类似于:
num #instances #bytes class name
----------------------------------------------
1: 2284437 262114728 [C
2: 686409 124390432 [B
3: 363878 46799288 <constMethodKlass>
4: 363878 46590464 <methodKlass>
5: 1817209 43613016 java.lang.String
6: 34590 37296528 <constantPoolKlass>
7: 296302 36673344 [I
8: 34585 33237656 <instanceKlassKlass>
9: 248731 21559504 [Ljava.lang.Object;
10: 28200 19991872 <constantPoolCacheKlass>
11: 563323 13519752 scala.collection.immutable.$colon$colon
12: 26813 13103488 <methodDataKlass>
13: 506968 12167232 scala.collection.immutable.HashSet$HashSet1
14: 200750 10371320 [Lscala.collection.immutable.HashSet;
15: 114268 9477096 [Lscala.collection.immutable.HashMap;
16: 92405 7392400 java.lang.reflect.Method
17: 200953 6430496 scala.collection.immutable.HashMap$HashMap1
Run Code Online (Sandbox Code Playgroud)
举例来说:“字节”到底显示什么?
jmap ×10
java ×9
jvm ×5
heap-dump ×3
memory ×2
profiling ×2
crash-dumps ×1
heap-memory ×1
jstack ×1
jvisualvm ×1
performance ×1
permgen ×1