找出java中的内存分配热点

时间:2012-11-12 14:32:21

标签: java performance memory-management garbage-collection jvm

我们的GC正在努力工作,我们想要减少一些暂停。 我们在使用实际的JVM GC args进行调整之前或期间要解决一些内存分配问题。

我想知道哪些物品让GC出汗:

  1. 有没有办法知道每次GC都撤离哪些对象 工作中?
  2. 有一种方法可以知道哪些对象在它们之间移动 GC每次运行时都会出现哪些区域?
  3. 有没有办法知道哪些物品在伊甸园区?
  4. 我正在与Jprofiler和Memory Analyzer广泛合作。 我想在我的暂存环境中获取有关正在运行的应用程序的此信息。

5 个答案:

答案 0 :(得分:4)

对于2和3,您可以在应用程序的运行会话期间将-XX:+PrintGCDetails-XX:+PrintGCTimeStamps标志与Oracle或OpenJDK java可执行文件一起使用

答案 1 :(得分:2)

对于问题1,可以使用Phantom References。这将允许您在对象是GC(或GC能够)时收到通知。

至于其他两个,我不太清楚。

答案 2 :(得分:2)

在正在运行的JVM中查找内存分配可能需要付出很大努力。

相反,您可以结帐热点source code并在GC或分配时添加自己的日志。编译自己的热点并跟踪日志。


使用-XX:+PrintCompilation可以帮助您。

-XX:+PrintCompilation标志输出如下所示:

1  sb   java.lang.ClassLoader::loadClassInternal  (6 bytes)     
2  b    java.lang.String::lastIndexOf  (12 bytes)
3  s!b  java.lang.ClassLoader::loadClass  (58 bytes)

标志对应于:

b    Blocking compiler (always set for client)  
*    Generating a native wrapper    
%    On stack replacement   
!    Method has exception handlers  
s    Synchronized method    

More details

答案 3 :(得分:2)

我们可能会尝试使用一些字节代码检测来添加finalize(可能是Object),它会在日志中提供这些信息。

答案 4 :(得分:1)

OldGen空间的内容:您可以找到OldGen中的对象。您需要在Full GC之前和之后打印直方图:-XX:+PrintClassHistogramBeforeFullGC -XX:+PrintClassHistogramAfterFullGC。由于YoungGen集合在Full GC之前执行,因此这些直方图将显示旧代的内容

检测过早提升的对象:要确定是否提前提升了任何实例,您需要研究直方图以查看预期在OldGen中应包含哪些类以及哪些类应该是仅在YoungGen中看到。这不能自动完成,您需要推断每个类及其实例的目的,以确定该对象是否是临时的。

YoungGen / Eden空间的内容:我还没有找到一种方法来区分哪些物体存在,例如在伊甸园。您可能知道, jProfiler MemoryAnalyzer 可以转储堆,但这不会告诉您对象所在的区域。但是,您也可以定期获取直方图快照,然后编写一个简单的脚本来解析输出并告诉您哪些实例增长最快,使用:jmap -histo $pid