JVM工具系列第5篇-jhat:虚拟机堆转储快照分析工具

star2017 1年前 ⋅ 357 阅读

目录

jhat

jhat也是jdk内置的工具之一。主要是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言。

使用jmap等方法生成java的堆文件后,使用其进行分析。

示例:

运行代码

  1. package com.jvm.test8;
  2. import lombok.*;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.UUID;
  6. import java.util.concurrent.TimeUnit;
  7. public class Test8 {
  8. @Getter
  9. @Setter
  10. @ToString
  11. @Builder
  12. @NoArgsConstructor
  13. @AllArgsConstructor
  14. public static class User {
  15. private String name;
  16. }
  17. public static void main(String[] args) throws InterruptedException {
  18. List<User> list = new ArrayList<>();
  19. for (int i = 0; i < 3000; i++) {
  20. for (int j = 0; j < 1000; j++) {
  21. list.add(User.builder().name(UUID.randomUUID().toString()).build());
  22. }
  23. TimeUnit.SECONDS.sleep(1);
  24. }
  25. }
  26. }

导出程序执行的堆信息

  1. C:\Users\Think>jps -l
  2. 13120 com.jvm.test8.Test8
  3. 13892
  4. 19044 org.jetbrains.idea.maven.server.RemoteMavenServer
  5. 9844 org.jetbrains.jps.cmdline.Launcher
  6. 19564 sun.tools.jps.Jps
  7. C:\Users\Think>jmap -dump:format=b,file=D:/1.hprof 13120
  8. Dumping heap to D:\1.hprof ...
  9. File exists
  10. C:\Users\Think>jmap -dump:format=b,file=D:/1.hprof 13120
  11. Dumping heap to D:\1.hprof ...
  12. Heap dump file created

使用jhat分析堆文件

  1. C:\Users\Think>jhat D:/1.hprof
  2. Reading from D:/1.hprof...
  3. Dump file created Sun Jun 02 13:01:44 CST 2019
  4. Snapshot read, resolving...
  5. Resolving 2101210 objects...
  6. Chasing references, expect 420 dots....................................................................................................................................................................................................................................................................................................................................................................................................................................
  7. Eliminating duplicate references....................................................................................................................................................................................................................................................................................................................................................................................................................................
  8. Snapshot resolved.
  9. Started HTTP server on port 7000
  10. Server is ready.

查看html

  • 访问:http://localhost:7000/
    file

分析内存泄露问题主要会用到“Show heap histogram”“”和“OQL”,前者可以找到内存中总容量最大的对象,后者是标准的对象查询语言,使用类似于SQL的语法对内存对象进行查询统计。

  • 显示出堆中所包含的所有的类
    file
    file

  • 从根集能引用到的对象
    file
    file

  • 显示所有类(包括平台)的实例计数
    file
    file

  • 堆实例的分布表
    file
    file

  • 执行对象查询语句
    file
    file

输入内容如:
查询长度大于100的字符串
select s from java.lang.String s where s.count > 100
详细的OQL可点击上图的“OQL help”

  1. jhat中的OQL(对象查询语言) ,把胡子文档可以查看:http://localhost:7000/oqlhelp/
  2. 如果需要根据某些条件来过滤或查询堆的对象,这是可能的,可以在jhathtml页面中执行OQL,来查询符合条件的对象
  3. 基本语法:
  4. select <javascript expression to select>
  5. [from [instanceof] <class name> <identifier>]
  6. [where <javascript boolean expression to filter>]
  7. 解释:
  8. (1)class namejava类的完全限定名,如:java.lang.String, java.util.ArrayList, [Cchar数组, [Ljava.io.Filejava.io.File[]
  9. (2)类的完全限定名不足以唯一的辨识一个类,因为不同的ClassLoader载入的相同的类,它们在jvm中是不同类型的
  10. (3)instanceof表示也查询某一个类的子类,如果不明确instanceof,则只精确查询class name指定的类
  11. (4)fromwhere子句都是可选的
  12. (5)java域表示:obj.field_namejava数组表示:array[index]
  13. 举例:
  14. (1)查询长度大于100的字符串
  15. select s from java.lang.String s where s.count > 100
  16. (2)查询长度大于256的数组
  17. select a from [I a where a.length > 256
  18. (3)显示匹配某一正则表达式的字符串
  19. select a.value.toString() from java.lang.String s where /java/(s.value.toString())
  20. (4)显示所有文件对象的文件路径
  21. select file.path.value.toString() from java.io.File file
  22. (5)显示所有ClassLoader的类名
  23. select classof(cl).name from instanceof java.lang.ClassLoader cl
  24. (6)通过引用查询对象
  25. select o from instanceof 0xd404d404 o
  26. built-in对象 -- heap
  27. (1)heap.findClass(class name) -- 找到类
  28. select heap.findClass("java.lang.String").superclass
  29. (2)heap.findObject(object id) -- 找到对象
  30. select heap.findObject("0xd404d404")
  31. (3)heap.classes -- 所有类的枚举
  32. select heap.classes
  33. (4)heap.objects -- 所有对象的枚举
  34. select heap.objects("java.lang.String")
  35. (5)heap.finalizables -- 等待垃圾收集的java对象的枚举
  36. (6)heap.livepaths -- 某一对象存活路径
  37. select heaplivepaths(s) from java.lang.String s
  38. (7)heap.roots -- 堆根集的枚举
  39. 辨识对象的函数
  40. (1)classof(class name) -- 返回java对象的类对象
  41. select classof(cl).name from instanceof java.lang.ClassLoader cl
  42. (2)identical(object1,object2) -- 返回是否两个对象是同一个实例
  43. select identical(heap.findClass("java.lang.String").name, heap.findClass("java.lang.String").name)
  44. (3)objectid(object) -- 返回对象的id
  45. select objectid(s) from java.lang.String s
  46. (4)reachables -- 返回可从对象可到达的对象
  47. select reachables(p) from java.util.Properties p -- 查询从Properties对象可到达的对象
  48. select reachables(u, "java.net.URL.handler") from java.net.URL u -- 查询从URL对象可到达的对象,但不包括从URL.handler可到达的对象
  49. (5)referrers(object) -- 返回引用某一对象的对象
  50. select referrers(s) from java.lang.String s where s.count > 100
  51. (6)referees(object) -- 返回某一对象引用的对象
  52. select referees(s) from java.lang.String s where s.count > 100
  53. (7)refers(object1,object2) -- 返回是否第一个对象引用第二个对象
  54. select refers(heap.findObject("0xd4d4d4d4"),heap.findObject("0xe4e4e4e4"))
  55. (8)root(object) -- 返回是否对象是根集的成员
  56. select root(heap.findObject("0xd4d4d4d4"))
  57. (9)sizeof(object) -- 返回对象的大小
  58. select sizeof(o) from [I o
  59. (10)toHtml(object) -- 返回对象的html格式
  60. select "<b>" + toHtml(o) + "</b>" from java.lang.Object o
  61. (11)选择多值
  62. select {name:t.name?t.name.toString():"null",thread:t} from instanceof java.lang.Thread t
  63. 数组、迭代器等函数
  64. (1)concat(enumeration1,enumeration2) -- 将数组或枚举进行连接
  65. select concat(referrers(p),referrers(p)) from java.util.Properties p
  66. (2)contains(array, expression) -- 数组中元素是否满足某表达式
  67. select p from java.util.Properties where contains(referres(p), "classof(it).name == 'java.lang.Class'")
  68. 返回由java.lang.Class引用的java.util.Properties对象
  69. built-in变量
  70. it -- 当前的迭代元素
  71. index -- 当前迭代元素的索引
  72. array -- 被迭代的数组
  73. (3)count(array, expression) -- 满足某一条件的元素的数量
  74. select count(heap.classes(), "/java.io./(it.name)")
  75. (4)filter(array, expression) -- 过滤出满足某一条件的元素
  76. select filter(heap.classes(), "/java.io./(it.name)")
  77. (5)length(array) -- 返回数组长度
  78. select length(heap.classes())
  79. (6)map(array,expression) -- 根据表达式对数组中的元素进行转换映射
  80. select map(heap.classes(),"index + '-->' + toHtml(it)")
  81. (7)max(array,expression) -- 最大值, min(array,expression)
  82. select max(heap.objects("java.lang.String"),"lhs.count>rhs.count")
  83. built-in变量
  84. lhs -- 左边元素
  85. rhs -- 右边元素
  86. (8)sort(array,expression) -- 排序
  87. select sort(heap.objects('[C'),'sizeof(lhs)-sizeof(rhs)')
  88. (9)sum(array,expression) -- 求和
  89. select sum(heap.objects('[C'),'sizeof(it)')
  90. (10)toArray(array) -- 返回数组
  91. (11)unique(array) -- 唯一化数组

最新资料

更多内容请访问:IT源点

全部评论: 0

    我有话说: