我想知道Java进程在特定时间使用的总堆大小是多少,我必须使用jmap.
输出jmap -heap <pid>给我这样的东西:
Attaching to process ID 2899, please wait... Debugger attached successfully. Server compiler detected. JVM version is 14.2-b01 using thread-local object allocation. Parallel GC with 2 thread(s) Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 1258291200 (1200.0MB) NewSize = 1048576 (1.0MB) MaxNewSize = 4294901760 (4095.9375MB) OldSize = 4194304 (4.0MB) NewRatio = 8 SurvivorRatio = 8 PermSize = 16777216 (16.0MB) MaxPermSize = 67108864 (64.0MB) Heap Usage: PS Young Generation Eden Space: capacity = 119013376 …
我理解新的gen/old gen/perm gen之间的区别,但我不知道"To Space"和"From Space"是什么.我看到我的"From Space"达到99.8%,而"To Space"似乎总是保持0%使用.
我们正试图在我们的Web应用程序中找到大内存泄漏的罪魁祸首.我们在查找内存泄漏方面经验非常有限,但我们发现如何jmap在Eclipse MAT中使用和分析它来进行Java堆转储.
但是,我们的应用程序使用56/60GB内存,堆转储的大小只有16GB,在Eclipse MAT中甚至更少.
我们的服务器在Ubuntu 14.04上使用Wildfly 8.2.0作为我们的Java应用程序,其进程使用95%的可用内存.进行转储时,我们的缓冲区/缓存已用空间为56GB.
我们使用以下命令创建转储: sudo -u {application user} jmap -dump:file=/mnt/heapdump/dump_prd.bin {pid}
堆转储文件大小为16,4GB,当使用Eclipse MAT进行分析时,它表示有大约1GB的活动对象和大约14,8GB的无法访问/浅堆.
编辑:这里有一些关于我们看到的问题的更多信息.我们监视内存使用情况,我们看到它的增长和增长,直到剩下大约300mb的可用内存.然后它保持在那个内存量附近,直到进程崩溃,不幸的是在应用程序日志中没有错误.
这使我们假设它是一个硬OOM错误,因为这只发生在内存接近耗尽时.我们使用-Xms25000m -Xmx40000mJVM 的设置.
基本上,我们想知道为什么我们的大部分内存都没有在这个转储中被捕获.顶部保留的大小类看起来并不太可疑,所以我们想知道是否存在与堆转储有关的问题我们做错了什么.
我们已经让我们的glassfish实例每两周下降一段时间java.lang.OutOfMemoryError: PermGen space.我将PermGen空间增加到512MB,并将startet转储内存使用量jstat -gc.两周后,我想出了下图,显示了PermGen空间是如何稳定增加的(x轴上的单位是分钟,y轴是KB).

我试着用谷歌搜索某种可以查明错误的分析工具,并在SO上提到一个线程提到jmap,这被证明是非常有帮助的.在倾倒的大约14000行中jmap -permstats $PID,大约包含12500行groovy/lang/GroovyClassLoader$InnerLoader,指向我们自己的Groovy代码或Groovy本身的某种内存泄漏.我必须指出,Groovy构造的相关代码库不到1%.
示例输出如下:
class_loader classes bytes parent_loader alive? type
<bootstrap> 3811 14830264 null live <internal>
0x00007f3aa7e19d20 20 164168 0x00007f3a9607f010 dead groovy/lang/GroovyClassLoader$InnerLoader@0x00007f3a7afb4120
0x00007f3aa7c850d0 20 164168 0x00007f3a9607f010 dead groovy/lang/GroovyClassLoader$InnerLoader@0x00007f3a7afb4120
0x00007f3aa5d15128 21 181072 0x00007f3a9607f010 dead groovy/lang/GroovyClassLoader$InnerLoader@0x00007f3a7afb4120
0x00007f3aad0b40e8 36 189816 0x00007f3a9d31fbf8 dead org/apache/jasper/servlet/JasperLoader@0x00007f3a7d0caf00
....
Run Code Online (Sandbox Code Playgroud)
那么我该如何进一步了解导致此问题的代码呢?
在本文中,我推断我们的Groovy代码是在某处动态创建类.从jmap的转储我可以看到大多数死对象/类(?)都有相同的parent_loader,虽然我不确定这在这个上下文中意味着什么.我不知道怎么从这里开始.
对于后来者来说,值得指出的是,接受的答案并不能解决问题.它只是通过不存储如此多的类信息来延长重启前所需的时间十倍.实际修复我们问题的是摆脱生成它的代码.我们使用验证(按合同设计)框架OVal,其中可以使用Groovy编写自定义约束作为方法和类的注释.在普通Java中删除注释以支持显式的前置条件和后置条件是很无聊的,但它完成了工作.我怀疑每次检查OVal约束时都会创建一个新的匿名类,并且关联的类数据以某种方式导致内存泄漏.
我们正在研究客户端的生产服务器堆,以检测和解决内存泄漏问题.为此,我们定期使用jmap来收集必要的信息.
但是上周我们无法进行转储,因为它触发了EOF错误并关闭了Tomcat实例.
我在互联网上搜索,但找不到有关此错误的任何具体信息.我们检测到只有在使用Gc First垃圾收集器算法时才会发生.
这是我们用来执行jmap的命令行:
jmap -dump:format=b,file=heap.bin <PID>
服务器上的Java版本:JDK 1.7.0_7 x64
有没有人遇到过这种错误?可能缺少一些配置或需要java/jmap的补丁.
UPDATE
我们收集的有关此错误的更多信息:
[root]# jmap -dump:format=b,file=heap.bin 7806
Dumping heap to /tmp/heap.bin ...
Exception in thread "main" java.io.IOException: Premature EOF
at sun.tools.attach.HotSpotVirtualMachine.readInt(HotSpotVirtualMachine.java:244)
at sun.tools.attach.LinuxVirtualMachine.execute(LinuxVirtualMachine.java:193)
at sun.tools.attach.HotSpotVirtualMachine.executeCommand(HotSpotVirtualMachine.java:213)
at sun.tools.attach.HotSpotVirtualMachine.dumpHeap(HotSpotVirtualMachine.java:180)
at sun.tools.jmap.JMap.dump(JMap.java:241)
at sun.tools.jmap.JMap.main(JMap.java:140)
[root]#
Run Code Online (Sandbox Code Playgroud)
注意:目标目录有超过500GB的可用空间
错误输出到catalina.out(JVM转储错误):
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f0269cc41c6, pid=7806, tid=139647231129360
#
# JRE version: Java(TM) SE Runtime Environment (7.0_40-b43) (build 1.7.0_40-b43)
# …Run Code Online (Sandbox Code Playgroud) 当我使用jmap获取有关进程的堆信息时,我得到了这样的错误:
$jmap -heap process_id
Attaching to process ID process_id, please wait...
Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: cannot open binary
file
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException:
cannot open binary file
Run Code Online (Sandbox Code Playgroud)
操作系统:Ubuntu 14.04
我DebuggerException: Can't attach to the process通过更新解决了另一个错误()kernel.yama.ptrace_scope = 0.
我解决了一个奇怪的内存泄漏问题.它特定于Java8,而不是在7u79上发生.
我无权访问Java代码.我确切知道哪个用户操作导致泄漏,我知道泄漏是关于类(而不是堆),并且使用+ TraceClassLoading + TraceClassUnloading很容易发现有问题的类:
[Loaded com.mastercard.mcwallet.sdk.xml.allservices.ShoppingCartRequest$JaxbAccessorF_oAuthToken from __JVM_DefineClass__]
[Loaded com.mastercard.mcwallet.sdk.... thousand similar classes per one user action... ]
Run Code Online (Sandbox Code Playgroud)
这些类似乎通过以下方式增加类计数器输出jstat -class:
Loaded Bytes Unloaded Bytes Time
14045 26138.8 0 0.0 110.00 << buggy user action
14675 26754.6 0 0.0 110.05
15300 27364.9 0 0.0 110.10
15304 27370.9 0 0.0 110.11
15304 27370.9 0 0.0 110.11
15304 27370.9 0 0.0 110.11
15306 27374.0 0 0.0 110.11
15306 27374.0 0 0.0 110.11
15306 27374.0 0 0.0 110.11
15306 27374.0 0 …Run Code Online (Sandbox Code Playgroud) 有一个Java核心转储; 运行jmap:
/usr/java/jdk1.8.0_25/bin/jmap -dump:format=b,file=dump.hprof /usr/bin/java core.31497
Run Code Online (Sandbox Code Playgroud)
给出以下例外:
Attaching to core core.31497 from executable /usr/bin/java, please wait...
...
JVM version is 25.25-b02
...
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sun.tools.jmap.JMap.runTool(JMap.java:201)
at sun.tools.jmap.JMap.main(JMap.java:130)
Caused by: sun.jvm.hotspot.utilities.AssertionFailure: can not get class data for sun/nio/ch/ThreadPool$$Lambda$10x00000007c0214428
at sun.jvm.hotspot.utilities.Assert.that(Assert.java:32)
at sun.jvm.hotspot.utilities.HeapHprofBinWriter.writeInstance(HeapHprofBinWriter.java:803)
...
at sun.jvm.hotspot.tools.Tool.start(Tool.java:223)
at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
at sun.jvm.hotspot.tools.HeapDumper.main(HeapDumper.java:83)
Run Code Online (Sandbox Code Playgroud)
有什么想法吗?
长话短说,一些同事正在运行一个非常古老的设置(x86_64中的oc4j jdk1.5.6),其中一个应用程序恰好是关键任务.他们最近尝试部署新版本的应用程序,但是一旦他们执行java进程就会抛出核心转储并死掉.
问题是,核心转储看起来很好,gdb可以打开它们,但jmap和其他工具拒绝处理它们:
# /usr/java/jdk1.5.0_06/bin/jmap /usr/java/jdk1.5.0_06/bin/java core
Attaching to core core from executable /usr/java/jdk1.5.0_06/bin/java, please wait...
Error attaching to core file: Can't attach to the core file
Run Code Online (Sandbox Code Playgroud)
更新的版本抛出异常:
# jdk1.6.0_45/bin/jmap /usr/java/jdk1.5.0_06/bin/java core
Attaching to core core from executable /usr/java/jdk1.5.0_06/bin/java, please wait...
Exception in thread "main" java.lang.reflect.InvocationTargetException
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.jmap.JMap.runTool(JMap.java:179)
at sun.tools.jmap.JMap.main(JMap.java:110)
Caused by: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 20.45-b01. Target VM is 1.5.0_06-b05
at sun.jvm.hotspot.runtime.VM.checkVMVersion(VM.java:224)
at sun.jvm.hotspot.runtime.VM.<init>(VM.java:287)
at sun.jvm.hotspot.runtime.VM.initialize(VM.java:357)
at sun.jvm.hotspot.bugspot.BugSpotAgent.setupVM(BugSpotAgent.java:594)
at sun.jvm.hotspot.bugspot.BugSpotAgent.go(BugSpotAgent.java:494) …Run Code Online (Sandbox Code Playgroud)