排查Java的内存问题(2)

java -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xmx20m -XX:+HeapDumpOnOutOfMemoryError oom
0.402: [GC (Allocation Failure) [PSYoungGen: 5564K->489K(6144K)] 5564K->3944K(19968K), 0.0196154 secs] [Times: user=0.05 sys=0.00, real=0.02 secs]
0.435: [GC (Allocation Failure) [PSYoungGen: 6000K->496K(6144K)] 9456K->8729K(19968K), 0.0257773 secs] [Times: user=0.05 sys=0.00, real=0.03 secs]
0.469: [GC (Allocation Failure) [PSYoungGen: 5760K->512K(6144K)] 13994K->13965K(19968K), 0.0282133 secs] [Times: user=0.05 sys=0.00, real=0.03 secs]
0.499: [Full GC (Ergonomics) [PSYoungGen: 512K->0K(6144K)] [ParOldGen: 13453K->12173K(13824K)] 13965K-
>12173K(19968K), [Metaspace: 2922K->2922K(1056768K)], 0.6941054 secs] [Times: user=1.45 sys=0.00, real=0.69 secs] 1.205: [Full GC (Ergonomics) [PSYoungGen: 5632K->2559K(6144K)] [ParOldGen: 12173K->13369K(13824K)] 17805K-
>15929K(19968K), [Metaspace: 2922K->2922K(1056768K)], 0.3933345 secs] [Times: user=0.69 sys=0.00, real=0.39 secs]
1.606: [Full GC (Ergonomics) [PSYoungGen: 4773K->4743K(6144K)] [ParOldGen: 13369K->13369K(13824K)] 18143K-
>18113K(19968K), [Metaspace: 2922K->2922K(1056768K)], 0.3009828 secs] [Times: user=0.72 sys=0.00, real=0.30 secs]
1.911: [Full GC (Allocation Failure) [PSYoungGen: 4743K->4743K(6144K)] [ParOldGen: 13369K->13357K(13824K)] 18113K-
>18101K(19968K), [Metaspace: 2922K->2922K(1056768K)], 0.6486744 secs] [Times: user=1.43 sys=0.00, real=0.65 secs]
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid26504.hprof ...
Heap dump file created [30451751 bytes in 0.510 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

at java.util.Arrays.copyOf(Arrays.java:3210)
 at java.util.Arrays.copyOf(Arrays.java:3181)
 at java.util.ArrayList.grow(ArrayList.java:261)
 at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
 at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
 at java.util.ArrayList.add(ArrayList.java:458)
 at oom.main(oom.java:14)

请注意,并行垃圾收集器可能会连续地调用Full GC以便于释放堆上的空间,即便这种尝试的收益很小、堆空间几乎已被充满时,它可能也会这样做。为了避免这种情况的发生,我们可以调节-XX:GCTimeLimit 和-XX:GCHeapFreeLimit的值。

GCTimeLimit能够设置一个上限,指定GC时间所占总时间的百分比。它的默认值是98%。减少这个值会降低垃圾收集所允许花费的时间。GCHeapFreeLimit设置了一个下限,它指定了垃圾收集后应该有多大的空闲区域,这是一个相对于堆的总小大的百分比。它的默认值是2%。增加这个值意味着在GC后要回收更大的堆空间。如果五次连续的Full GC都不能保持GC的成本低于GCTimeLimit并且无法释放 GCHeapFreeLimit所要求的空间的话,将会抛出OutOfMemoryError。

例如,将GCHeapFreeLimit设置为8%的话,如果连续五次垃圾收集无法回收至少8%的堆空间并且超出了GCTimeLimit设置的值,这样能够帮助垃圾收集器避免连续调用Full GC的情况出现。

堆直方图

有时,我们需要快速查看堆中不断增长的内容是什么,绕过使用内存分析工具收集和分析堆转储的漫长处理路径。堆直方图能够为我们快速展现堆中的对象,并对比这些直方图,帮助我们找到Java堆中增长最快的是哪些对象。

-XX:+PrintClassHistogram以及Control+Break

jcmd <process id/main class> GC.class_histogram filename=Myheaphistogram

jmap -histo pid

jmap -histo <java> core_file

下面的示例输出显示String、Double、Integer和Object[]的实例占据了Java堆中大多数的空间,并且随着时间的流逝数量在不断增长,这意味着它们可能会导致内存泄露:

排查Java的内存问题

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/8897945a0be00fadb00880f35eefe05e.html