我正在尝试使用以下 2 个命令进行堆转储
jcmd 产生 ~300M 的文件大小,jmap 产生 ~1.4G 的文件大小。为什么这些是不同的大小,我们在 jmap 中有任何其他信息吗?我在 jcmd 中遗漏了一些参数吗?
JDK 是 1.8.0_162
Xms 和 Xmx 是 4G
在Linux机器(以及很可能是Unix机器)中生成的Java堆转储具有受限访问权限.堆只能由进程的所有者读取(ACL掩码设置为600).我知道这是出于安全原因.但是,我无法找到任何引用或解释行为的文档.任何人都可以指向我的文档(如果有的话)?另外,有没有办法覆盖这种行为?
我有一个java程序,它一直调用java.util.zip
压缩/解压缩数据.它会在几秒钟内耗尽内存.我有一个内存转储,jmap
我正在查看它jhat
.
终结器摘要显示Total instances pending finalization: 0
.如果我理解正确,我没有任何对象(1)有finalize()方法,(2)已经被GC标记,(3)等待最终确定.这似乎很好.
当我查看特定对象时,对该对象的唯一引用是a java.lang.ref.Finalizer
.无论对象是否为GC,都会为每个具有finalize()方法的对象创建Finalizer对象.所以看起来没有什么能阻止这个Deflater
对象被GC控制.
对象位于0x7f4aeb7a35d0
java.util.zip.Deflater@0x7f4aeb7a35d0的实例(51个字节)
对此对象的引用:
java.lang.ref.Finalizer@0x7f4aeb8607c8(64字节):字段指示对象
该程序暂停运行System.in.read()
.一段时间后内存使用量不会下降.
更新:
我应该说清楚.内存转储显示许多对象没有GC,但没有其他对象(Finalizer对象除外)引用它们.我试图找出他们为什么不是GC的.
在少数情况下,我们的应用程序使用大约12 GB的内存.我们尝试使用jmap实用程序获取堆转储.由于应用程序使用了一些GB内存,因此会导致应用程序停止响应并导致生产中出现问题.
在我们的例子中,堆使用量在6小时内突然从2-3 GB增加到12 GB.为了找到内存使用趋势,我们尝试在重新启动应用程序后每隔一小时收集一次堆转储.但正如所说,因为使用jmap导致应用程序挂起,我们需要重新启动它,我们无法获得内存使用的趋势.
有没有办法在不挂起应用程序的情况下获取堆转储,或者是否有除jmap之外的实用程序来收集堆转储.
关于这一点的想法受到高度赞赏,因为没有得到内存使用的趋势,很难解决这个问题.
注意:我们的应用程序在CentOS中运行.
谢谢,阿伦
我知道当在这个JVM上发生OutOfMemoryException时可以转储堆,但是可以用jmap或jconsole等工具询问实时转储吗?
我在ubuntu上,我需要确认tomcat正在使用堆大小设置.
我怎样才能做到这一点?
我试过jmap,但似乎没有在服务器上,我能以某种方式单独下载吗?
我正在尝试分析从遇到内存问题的 java 进程中获取的堆转储。转储是使用 jmap 获取的。我在转储文件上使用 jhat - 我得到
java.io.IOException: Unrecognized magic number: 169897589
at com.sun.tools.hat.internal.parser.Reader.readFile(Reader.java:94)
at com.sun.tools.hat.Main.main(Main.java:159)
jdk 1.6和1.7都给出相同的错误。我在 Windows 计算机上本地运行 jhat(将转储文件复制到 后),转储文件是在 Linux 服务器上获取的。
有什么想法我做错了吗?
我们有在生产中运行的 java 流服务器,它需要大约 10GB 的 RAM 才能运行,因此我们安装了 32GB。内存逐渐增加,直到达到限制并弹出内存不足异常。
由于直方图和内存转储数字与系统报告的内存使用情况不匹配,我无法确定哪些对象随着时间的推移而累积,即 java 进程占用的内存超过最大 20GB(因此内存不足异常是合理的)但直方图和内存dump 显示总共使用了 6.4GB。
process : 19.8G
Java
reported: 6.4G
---------------
unknown
occupied
segment : 13.4G
Run Code Online (Sandbox Code Playgroud)
如何在直方图中未显示的未知占用段中获取有关内存的信息?
我使用jmap -J-d64 -histo <pid> > <file>
命令生成直方图。
进程映射了以下内存段,按大小排序
0x2DE000000: 13333.5MB
0x61F580000: 6666.5MB
0x7C0340000: 1020.8MB
0x7FBFF33C9000: 716.2MB
0x7FC086A75000: 196.9MB
0x7FB85C000000: 64.0MB
0x7FBAC0000000: 64.0MB
...
Run Code Online (Sandbox Code Playgroud)
jmap 报告的所有 java 对象的总大小适合0x61F580000: 6666.5MB
段。
我的猜测是较大的段0x2DE000000: 13333.5MB
保存泄漏的对象,因为直方图显示了此应用程序的正常内存使用情况。
有没有办法找出什么占用了直方图中未包含的其他内存?
如何检测服务器的闭源部分是否使用本机扩展来分配系统内存而不是 java 内存?在那种情况下,我们不会看到内存不足异常,对吗?
这是 htop 输出:
Mem[|||||||||||||||||||||31670/31988MB] Tasks: 87; 35 running
Swp[|||||||||||||||||| 16361/32579MB] Load average: 39.33 36.00 …
Run Code Online (Sandbox Code Playgroud) jmap堆转储是仅包含旧代还是年轻代?
我有2堆dump(jmap -heap:format=b 9999
):
现在,第一个转储显示的堆大小比第二个大(我认为这很奇怪).
可能是因为Young Generation(高负载)经常变化,因为垃圾收集器经常运行(是的,JVM几乎已满)?老一代满99%,我注意到年轻一代的空间使用量差异很大.
所以这意味着我在GC完成他的工作后立即进行了第二次转储,这就是为什么它的尺寸更小.我对吗 ?
附加信息:
Java args:
-XX:+UseParallelGC -XX:+AggressiveHeap
-Xms2048m -Xmx4096m -XX:NewSize=64m
-XX:PermSize=64m -XX:MaxPermSize=512m
Run Code Online (Sandbox Code Playgroud) 在具有Oracle JDK 10.0.1-64bits的Ubuntu Mate 18.04-64bits上使用jmap时,该工具仅在同时以root身份运行目标和工具时才有效,但是使用同一普通用户运行这两者会产生以下错误:
Exception in thread "main" com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file /proc/13538/cwd/.attach_pid13538: target process 13538 doesn't respond within 10500ms or HotSpot VM not loaded
at jdk.attach/sun.tools.attach.VirtualMachineImpl.<init>(VirtualMachineImpl.java:103)
at jdk.attach/sun.tools.attach.AttachProviderImpl.attachVirtualMachine(AttachProviderImpl.java:58)
at jdk.attach/com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:207)
at jdk.jcmd/sun.tools.jmap.JMap.executeCommandForPid(JMap.java:124)
at jdk.jcmd/sun.tools.jmap.JMap.main(JMap.java:114)
Run Code Online (Sandbox Code Playgroud)
使用root用户运行以下命令时
jmap -clstats <pid>
Run Code Online (Sandbox Code Playgroud)