我们的 GC 正在努力工作,我们想要减少一些暂停。在调整实际 JVM GC 参数之前或期间,我们有一些内存分配问题想要解决。
我想知道哪些对象让 GC 出汗:
- 有没有办法知道每次 GC 工作时疏散了哪些对象?
- 有没有办法知道每次 GC 工作时哪些对象在区域之间移动?
- 有没有办法知道伊甸园区域中有哪些物体?
我正在广泛使用 Jprofiler 和 Memory Analyzer。我想在我的登台环境中获取有关正在运行的应用程序的信息。
我们的 GC 正在努力工作,我们想要减少一些暂停。在调整实际 JVM GC 参数之前或期间,我们有一些内存分配问题想要解决。
我想知道哪些对象让 GC 出汗:
我正在广泛使用 Jprofiler 和 Memory Analyzer。我想在我的登台环境中获取有关正在运行的应用程序的信息。
对于 2 和 3,您可以在应用程序的运行会话期间将-XX:+PrintGCDetails
and-XX:+PrintGCTimeStamps
标志与 Oracle 或 OpenJDK可执行文件一起使用java
我们可能会尝试使用一些字节码工具来添加 finalize(可能是对象),这将在日志中为我们提供这些信息。
对于问题 1, 可以使用Phantom References 。这将允许您在对象被 GC(或 GC-able)时收到通知。
至于另外两个,我不太清楚。
找出正在运行的 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
更多细节。
OldGen 空间的内容:您可以找出哪些对象驻留在 OldGen 中。您需要在 Full GC: 之前和之后打印直方图-XX:+PrintClassHistogramBeforeFullGC -XX:+PrintClassHistogramAfterFullGC
。并且由于 YoungGen 集合在 Full GC 之前执行,这些直方图将显示老年代的内容。
检测过早提升的对象:要确定是否有任何实例提前提升,您需要研究直方图以查看哪些类OldGen
应该驻留在YoungGen
. 这不能自动完成,您需要推理每个类及其实例的目的以确定对象是否是临时的。
YoungGen/Eden 空间的内容:我还没有找到一种方法来区分哪些对象驻留在例如 Eden 中。您可能知道,jProfiler和MemoryAnalyzer可以转储堆,但这不会告诉您对象驻留在哪个区域。但是,您也可以定期拍摄直方图快照,然后编写一个简单的脚本来解析输出并告诉您哪些实例增长最快,请使用 : jmap -histo $pid
。