1、如何看到老年代、新生代的对象有哪些呢?
MAT是分析dump的神器(顺便吐槽:当然也是吃内存卡机器的怪兽)。通常我们会在出现 fullGC 时 dump下堆内存,然后分析FullGC的原因。那如何获知整个堆内存里,有哪些对象在新生代、哪些在老年代呢?
一个典型的应用场景是:出现了耗时超预期的YoungGC,我们使用 【jstat -gcutil PID 1000】(每秒采一个点) 观察 Eden区的使用情况,在Eden 即将用满时 手动执行 【 jmap -dump:format=b,file=heap.hprof 】触发 Heap dump。然后分析到底是哪些对象 进入了新生代,导致YoungGC耗时这么长的。
这里要介绍下一些JVM 诊断工具了。
原生的JDK中已经有jps jstat jmap 等工具,但真用起来还是有点不太方便。比如 【jmap -histo PID】能够看到整个堆的对象统计信息,不能分代统计。国内二线厂出品的vjmap 命令倒是可以解决这个问题,下为 github地址:https://github.com/vipshop/vjtools/tree/master/vjmap
.
使用./vjmap.sh -address PID
打印得到heap地址区间,比如:
eden [0x0000000119000000,0x0000000119c4a258,0x0000000121880000) space capacity = 143130624, 9.003395387977907 used
from [0x0000000121880000,0x0000000121880000,0x0000000122990000) space capacity = 17891328, 0.0 used
to [0x0000000122990000,0x0000000122990000,0x0000000123aa0000) space capacity = 17891328, 0.0 used
concurrent mark-sweep generation
free-list-space[ 0x0000000123aa0000 , 0x0000000139000000 ) space capacity = 357957632 used(4%)= 17024696 free= 340932936
【来源于 github】
根据打印信息,得到 老年代的地址区间,拼成查询OQL:
SELECT * FROM INSTANCEOF java.lang.Object t WHERE toHex(t.@objectAddress) <= “0x123aa0000” AND toHex(t.@objectAddress) >= “0x139000000”
这里两个 十六进制地址,分别是上面的老年代地址上下界,注意去掉前面一串0.
再输入MAT的 OQL 查询框中,
然后,就能看到老年代对象了。
如果是希望看到新生代的对象,修改OQL 语句即可,这个和SQL有异曲同工之妙。