以前 jhat 自带 OQL,现在的 JDK 没有了。想「像查数据库一样查堆」,今天怎么做?这篇真的导出堆转储,用 Eclipse MAT 的批处理模式跑 OQL,再看不可达对象在转储里和在 MAT 里的区别。
(另一个进程)HotSpotDiagnosticMXBean.dumpHeap(path, live=false): 40.47 MB ;dumpHeap(path, live=true): 34.09 MB
jcmd <pid> GC.heap_dump -all f(先做,此时还没有 GC) 40.76 MB 耗时 0.21 s
jmap -dump:format=b,file=f <pid>(不带 live,同样没有先 GC) 40.76 MB 耗时 0.09 s
jcmd <pid> GC.heap_dump f(默认 live,会先做一次 GC) 34.07 MB 耗时 0.09 s
jmap -dump:live,format=b,file=f <pid> 34.07 MB 耗时 0.09 s
jcmd <pid> GC.heap_dump -gz=1 f(压缩) 2.41 MB 耗时 0.11 s
jhat(曾经带 OQL 的堆分析器)是否存在于 JDK 的 bin 目录: {'JDK 17': False, 'JDK 21': False} 年龄大于 65 的 User(字段读取与 toString())
SELECT u.name.toString() AS name, u.age AS age FROM Heap$User u WHERE u.age > 65
→ 40 行,1.6 s;表头 name,age,;前 4 行 ['user249,67,', 'user248,66,', 'user499,67,', 'user498,66,']
长度至少 500000 的 byte[]
SELECT * FROM byte[] b WHERE b.@length >= 500000
→ 6 行,1.0 s;表头 Class Name,Shallow Heap,Retained Heap,;前 6 行 ['byte[600000] @ 0x11f800000,600016,600016,', 'byte[700000] @ 0x11f900000,700016,700016,', 'byte[800000] @ 0x11fa00000,800016,800016,', 'byte[900000] @ 0x11fb00000,900016,900016,', 'byte[1000000] @ 0x11fc00000,1000016,1000016,', 'byte[500000] @ 0x12e0806c0,500016,500016,']
已过期的 Session 及其保留大小
SELECT s.id, s.@retainedHeapSize FROM Heap$Session s WHERE s.expired = true
→ 4000 行,0.9 s;表头 s.id,s.@retainedHeapSize,;前 3 行 ['49,4136,', '48,4136,', '47,4136,']
过期 Session 数 4000 ;保留大小合计 16544000 字节
以 dup- 开头的 String
SELECT toString(s) AS v, s.@retainedHeapSize AS retained FROM java.lang.String s WHERE toString(s).startsWith(\"dup-\")
→ 50002 行,2.1 s;表头 v,retained,;前 3 行 ['dup-5,48,', 'dup-4,48,', 'dup-3,48,']
不同取值 12 种;个数为 5000 的有 10 种;其余取值: ['dup-\\u0001', 'dup-'] ;这些 String 的保留大小合计 2400096 字节(其中每个 String 平均 48.0 字节)dumpHeap(live=true) 默认解析 长度 ≥ 5000000 的 byte[]: 0 个(查询没有结果) ;日志含 Removing unreachable objects: False dumpHeap(live=false) 默认解析 长度 ≥ 5000000 的 byte[]: 0 个(查询没有结果) ;日志含 Removing unreachable objects: True dumpHeap(live=false) + -keep_unreachable_objects 长度 ≥ 5000000 的 byte[]: 1 个 ['byte[5000000] @ 0x120d00000,5000016,5000016,'] ;日志含 Removing unreachable objects: True