Mat*_*oli 5 java memory heap jvm jmap
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)
Sea*_*ean 10
快速回答
两者 - 堆由年轻和老一代组成.因此,当您进行堆转储时,内容包含两者.应该分离堆转储的统计信息.尝试删除命令的二进制部分并以纯文本格式查看.您将看到配置摘要,然后是每一代的细分.另一方面,-histo只会显示堆上的所有对象而没有区别
答案很长
可能是垃圾收集刚刚完成第二个过程.或者相反,第一个过程可能在一段时间内没有完整的收集并且坐在更高的记忆中.捕获后,此应用程序/服务器是否刚刚重启?如果您使用类似的工具查看空闲进程jvisualvm,即使您的进程没有做任何工作,您也会看到内存分配图表上下移动.这只是JVM做自己的事情.
通常,您的Full GC应该在Old Gen中达到99%之前启动.JVM将决定何时运行完整的GC.你的Young Gen会波动很多,因为这是最快创建/删除对象的地方.在完整的GC运行之前,将会有许多部分GC用于清除年轻人.两者之间的差异将意味着您的JVM活动暂停.查看部分GC不会损害您的应用程序.但是完整GC的暂停时间将在运行时停止应用程序.所以你会希望尽可能地减少那些最好的.
如果您正在寻找内存泄漏或只是分析以查看您的应用程序gc是如何工作的,我建议使用启动标志来打印垃圾收集统计信息.
-XX:+PrintGCDetails -verbose:gc -Xloggc:/log/path/gc.log
Run Code Online (Sandbox Code Playgroud)
运行您的程序一段时间,然后将捕获的日志加载到工具中以帮助可视化结果.我个人使用IBM Support Assistant Workbench中提供的垃圾收集和内存可视化工具.它将为您提供捕获的垃圾收集统计信息的摘要以及一个动态图,您可以使用该图来查看应用程序中的内存是如何运行的.这不会给你堆上的对象.
在应用程序的问题时间,如果你可以暂停,我会修改你的jmap命令来执行以下操作
jmap -dump:format=b,file=/file/location/dump.hprof <pid>
Run Code Online (Sandbox Code Playgroud)
使用像MAT这样的工具,您将能够看到所有对象,泄漏嫌疑人以及关于代的各种其他统计信息,堆的引用.
编辑调整讨论
根据您的启动参数,您可以尝试一些操作
-XX:ParallelGCThreads=##.-XX:+UseParallelOldGC,显示了一些减少旧GC收集时间的承诺.我确实相信如果你如此快速地分配这么多内存,那么它可能是一代产生问题,其中内存过早地分配给老一代.如果对新gen大小的调整不起作用,那么您需要通过-Xmx配置添加更多堆,或者后退并找到确切地保留在内存中的内容.我们之前讨论过的MAT工具可以向您展示保留在内存中的对象的引用.我建议先尝试第1点和第4点.这将是试验和错误,以便您获得正确的值