Jmap堆转储,是否包括年轻一代?

时间:2011-05-19 11:47:07

标签: java memory jvm heap jmap

快速提问

jmap堆转储是仅包含旧代还是年轻代?


长解释

我有2个堆转储(jmap -heap:format=b 9999):

  • 我的一台没有负载的服务器(没有HTTP请求)
  • 一个工作50%CPU,高负载(基准测试)

现在,第一次转储显示堆大小比第二次(我觉得很奇怪)。

可能是因为Young Generation(高负载)经常发生变化,因为垃圾收集器经常运行(是的,JVM几乎已满)?老一代人满99%,我注意到年轻一代的空间使用量差异很大。

这意味着我在GC完成工作后立即进行了第二次转储,这就是为什么它的尺寸更小。我是对的吗?

附加信息

Java args:

-XX:+UseParallelGC -XX:+AggressiveHeap
-Xms2048m -Xmx4096m -XX:NewSize=64m
-XX:PermSize=64m -XX:MaxPermSize=512m

1 个答案:

答案 0 :(得分: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

运行程序一段时间,然后将捕获的日志加载到工具中以帮助可视化结果。我个人使用IBM Support Assistant Workbench中提供的Garbage Collection and Memory Visualizer。它将为您提供捕获的垃圾收集统计信息的摘要以及一个动态图,您可以使用该图来查看应用程序中的内存是如何运行的。这不会给你堆上的对象。

在应用程序的问题时间,如果您可以暂停,我会修改您的jmap命令以执行以下操作

jmap -dump:format=b,file=/file/location/dump.hprof <pid>

使用像MAT之类的工具,您将能够看到所有对象,泄漏嫌疑人以及有关代数,堆的引用的各种其他统计信息。

编辑调整讨论

根据您的启动参数,您可以尝试一些事项

  • 将-Xms设置为相同的值 作为你的-Xmx。通过这样做JVM 不必花时间分配 更堆。如果您希望您的应用程序需要4gb,请立即将其全部用完
  • 取决于处理器的数量 在你运行它的系统上 您可以为应用程序设置标志 -XX:ParallelGCThreads=##
  • 我没试过这个,但是 文档显示了一个参数 -XX:+UseParallelOldGC显示了减少旧GC时间的承诺 集合。
  • 尝试将新一代尺寸更改为堆的1/4。 (1024而不是64)这可能会迫使老一代过多。默认大小约为30%,您的应用程序配置为年轻人使用约2%。虽然你没有配置最大尺寸,但我担心太多数据会被移到旧版本,因为新版本太小而无法处理所有请求。因此,您必须执行更多完整(暂停)GC才能清理内存。

如果你如此快速地分配这么多内存,我确实相信,那么它可能是一个生成问题,其中内存过早地分配给老一代。如果对新的gen大小的调整不起作用,那么您需要通过-Xmx配置添加更多堆,或者后退并找到确切地保留在内存中的内容。我们之前讨论过的MAT工具可以向您展示保留在内存中的对象的引用。我建议尝试子弹点1&amp; 4首先。这将是试错,以便您获得正确的值