我们的GC正在努力工作,但是有一些暂停时间需要缩短。 我们希望在调整JVM GC参数时解决一些内存分配问题。
我想知道哪些对象会导致GC过度运行:
- 是否有一种方法可以知道每次GC运行时哪些对象被移走?
- 是否有一种方法可以知道每次GC运行时哪些对象在不同区域之间移动?
- 是否有一种方法可以知道哪些对象在Eden区域中?
我正在广泛使用Jprofiler和Memory Analyzer。 我希望在我的staging环境中的运行应用程序中获取这些信息。
我们的GC正在努力工作,但是有一些暂停时间需要缩短。 我们希望在调整JVM GC参数时解决一些内存分配问题。
我想知道哪些对象会导致GC过度运行:
我正在广泛使用Jprofiler和Memory Analyzer。 我希望在我的staging环境中的运行应用程序中获取这些信息。
对于2和3,您可以在应用程序运行期间使用Oracle或OpenJDK java
可执行文件的-XX:+PrintGCDetails
和-XX:+PrintGCTimeStamps
标志。
-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
更多细节。
我们可能会尝试使用一些字节码插装来添加finalize(可能是Object),这将在日志中提供给我们这些信息。
OldGen空间的内容:您可以查找哪些对象驻留在OldGen中。您需要在Full GC之前和之后打印直方图:-XX:+PrintClassHistogramBeforeFullGC -XX:+PrintClassHistogramAfterFullGC
。由于Full GC之前执行了YoungGen收集,因此这些直方图将向您展示Old generation的内容。
检测过早晋升的对象:为了确定是否有实例被提前晋升,您需要研究直方图,查看哪些类应该驻留在OldGen
中,哪些类只应该出现在YoungGen
中。这不能自动完成,您需要考虑每个类及其实例的目的,以确定该对象是否是临时的。
YoungGen/Eden空间的内容:我还没有找到一种方法来区分哪些对象驻留在Eden等区域。正如您可能知道的那样,jProfiler和MemoryAnalyzer可以转储堆,但这不会告诉您对象驻留在哪个区域。但是,您也可以定期拍摄直方图快照,然后编写一个简单的脚本来解析输出,并告诉您哪些实例增长最快,使用:jmap -histo $pid
。