From: 怎麼找到什麼東東被移到了老年代java
我怎麼找到都是什麼東東在轉移到老年代????!oracle
一個笨方法就是使用這個option 啓動java 應用: -XX:+TraceScavenge. 可是這個命令選項並無在正式JVM版本里發佈, 須要找到一個debug版本的HotSpot JVM才能使用這個命令選項。 用了這個命令以後, 日誌輸出很冗長, 由於它會每次每一個在年輕代被處理的對象。工具
還有一個可能的辦法就是從heap dumps中提取信息。 年輕代與用選項-XX:+PrintHeapAtGC獲得的對便捷信息配合使用獲得的heap dumps 能夠幫助咱們找到堆積在老年代的對象們。spa
用一個簡單的栗子演示下怎麼作,先用命令行啓動java 應用: 命令行
java -Xmx100m -XX:NewSize=10m -XX:+PrintGCDetails -XX:+HeapDumpBeforeFullGC -XX:+PrintHeapAtGC TestAppdebug
在4次年輕代回收以後, 老年代被填滿而且致使Full GC。這時JVM會生成Heap Dump。OK, 那就分析下這個自動生成的Heap Dump找出都是什麼東東轉移到老年代。日誌
GC 日誌裏顯示了在GC#4(第四次GC)先後堆內存使用狀況:對象
`{Heap before GC invocations=4 (full 0):
PSYoungGen total 17408K, used 17392K [0x00000000fdf00000, 0x0000000100000000, 0x0000000100000000)
eden space 16384K, 100% used [0x00000000fdf00000,0x00000000fef00000,0x00000000fef00000)
from space 1024K, 98% used [0x00000000fef00000,0x00000000feffc010,0x00000000ff000000)
to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
ParOldGen total 68608K, used 34096K [0x00000000f9c00000, 0x00000000fdf00000, 0x00000000fdf00000)
object space 68608K, 49% used [0x00000000f9c00000,0x00000000fbd4c000,0x00000000fdf00000)
Metaspace used 2612K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 285K, capacity 386K, committed 512K, reserved 1048576Kblog
[GC (Allocation Failure) [PSYoungGen: 17392K->1024K(32768K)] 51488K->52816K(101376K), 0.0101398 secs] [Times: user=0.00 sys=0.00, real=0.00內存
Heap after GC invocations=4 (full 0):
PSYoungGen total 32768K, used 1024K [0x00000000fdf00000, 0x0000000100000000, 0x0000000100000000)
eden space 31744K, 0% used [0x00000000fdf00000,0x00000000fdf00000,0x00000000ffe00000)
from space 1024K, 100% used [0x00000000fff00000,0x0000000100000000,0x0000000100000000)
to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
ParOldGen total 68608K, used 51792K [0x00000000f9c00000, 0x00000000fdf00000, 0x00000000fdf00000)
object space 68608K, 75% used [0x00000000f9c00000,0x00000000fce94050,0x00000000fdf00000)
Metaspace used 2612K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 285K, capacity 386K, committed 512K, reserved 1048576K
}
Heap Dump (before full gc): Dumping heap to java_pid31684.hprof ... ` 注意,ParOldGen中的object space的佔用內存明顯增多, 如今可使用MAT(memory analysis tool)打開java_pid31684.hprof。可是在使用MAT分析heap dump以前, 需配置'Keep unreachable objects'。Keep unreachable objects 啥意思??? -> 保持沒有被引用的對象。這樣作是爲了確保已經不在被引用,可是仍然存在於堆中的對象可以顯示在MAT中。如何設置 'Keep unreachable objects'? -> 工具欄中 Window->Preferences->Memory Analyzer 找到'keep unreachable objects'選中便可。
從上面的GC日誌中, 能夠看出老年代起始地址: 0x00000000f9c00000, 在GC#4以前,老年代的終止地址:0x00000000fbd4c000,在GC#4以後,老年代增長到的終止地址: 0x00000000fce94050。這意味着由於GC#4而轉移的對象在老年代的地址範圍爲 [0x00000000fbd4c000 ~ 0x00000000fce94050], 可使用OQL(Object Query Language) 查詢在這個地址範圍內的對象:
SELECT * FROM INSTANCEOF java.lang.Object t WHERE (toHex(t.@objectAddress) >= "0xfbd4c000" AND toHex(t.@objectAddress) <= "0xfce94050")