16

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

我想知道哪些对象让 GC 出汗:

  1. 有没有办法知道每次 GC 工作时疏散了哪些对象?
  2. 有没有办法知道每次 GC 工作时哪些对象在区域之间移动?
  3. 有没有办法知道伊甸园区域中有哪些物体?

我正在广泛使用 Jprofiler 和 Memory Analyzer。我想在我的登台环境中获取有关正在运行的应用程序的信息。

4

5 回答 5

4

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

于 2012-11-13T03:32:00.183 回答
2

我们可能会尝试使用一些字节码工具来添加 finalize(可能是对象),这将在日志中为我们提供这些信息。

于 2012-11-13T05:33:31.190 回答
2

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

至于另外两个,我不太清楚。

于 2012-11-12T15:12:44.017 回答
2

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

相反,您可以在 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    

更多细节

于 2012-11-13T02:36:40.237 回答
1

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

检测过早提升的对象:要确定是否有任何实例提前提升,您需要研究直方图以查看哪些类OldGen应该驻留在YoungGen. 这不能自动完成,您需要推理每个类及其实例的目的以确定对象是否是临时的。

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

于 2012-12-19T07:20:01.153 回答