JVM工具:使用 jmap 打印 Java 堆信息时报错:Can't attach symbolicator to the process

红太狼 2023-07-10 14:23 96阅读 0赞

一、问题描述

1、环境描述。
操作系统:Mac 10.14.6
JDK版本:1.8.0_241

2、Java 代码。
在 Idea 中执行以下代码:代码的逻辑是向 list 中添加 1000 条数据,之后 sleep 1000 秒。

  1. package org.learn.jmap;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /** * @author zhibo * @date 2020-03-03 11:09 */
  5. public class JmapTest {
  6. public static void main(String[] args) {
  7. try {
  8. List list = new ArrayList();
  9. for (int i = 0; i < 1000; i++) {
  10. list.add(i);
  11. }
  12. Thread.sleep(1000 * 1000);
  13. } catch (InterruptedException e) {
  14. e.printStackTrace();
  15. }
  16. }
  17. }

3、通过 jps 命令查看 Java 进程 pid 和 名称。
本例中测试进程名为 JmapTest,它对应的 pid 为 32845。

  1. zhibo-mac:JavaVirtualMachines zhibo$ jps
  2. 32848 Jps
  3. 27568 sun.jvm.hotspot.SALauncher
  4. 2099
  5. 32844 Launcher
  6. 32845 JmapTest
  7. zhibo-mac:JavaVirtualMachines zhibo$

4、通过 jmap -heap pid 打印 Java 堆的概要信息。
执行命令后,错误提示如下,问题的核心为:Can't attach symbolicator to the process

  1. zhibo-mac:JavaVirtualMachines zhibo$ jmap -heap 32845
  2. Attaching to process ID 32845, please wait...
  3. Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach symbolicator to the process sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: Can't attach symbolicator to the process
  4. at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal$BsdDebuggerLocalWorkerThread.execute(BsdDebuggerLocal.java:169)
  5. at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.attach(BsdDebuggerLocal.java:287)
  6. at sun.jvm.hotspot.HotSpotAgent.attachDebugger(HotSpotAgent.java:671)
  7. at sun.jvm.hotspot.HotSpotAgent.setupDebuggerDarwin(HotSpotAgent.java:659)
  8. at sun.jvm.hotspot.HotSpotAgent.setupDebugger(HotSpotAgent.java:341)
  9. at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:304)
  10. at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140)
  11. at sun.jvm.hotspot.tools.Tool.start(Tool.java:185)
  12. at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
  13. at sun.jvm.hotspot.tools.HeapSummary.main(HeapSummary.java:49)
  14. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  15. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  16. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  17. at java.lang.reflect.Method.invoke(Method.java:498)
  18. at sun.tools.jmap.JMap.runTool(JMap.java:201)
  19. at sun.tools.jmap.JMap.main(JMap.java:130)
  20. Caused by: sun.jvm.hotspot.debugger.DebuggerException: Can't attach symbolicator to the process
  21. at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.attach0(Native Method)
  22. at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.access$100(BsdDebuggerLocal.java:65)
  23. at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal$1AttachTask.doit(BsdDebuggerLocal.java:278)
  24. at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal$BsdDebuggerLocalWorkerThread.run(BsdDebuggerLocal.java:144)

二、问题分析

对于这类未知的问题,我们的做法是上百度、谷歌查找该问题产生的原因。通过谷歌找到 Java 官方对该问题的说明,该问题是由于 JDK 的 bug 导致的,在 JDK9 中已经解决了该问题。具体内容见:JDK-8160376 : DebuggerException: Can’t attach symbolicator to the process 。

三、问题解决

1、继续安装 JDK11,这里我没有删除 JDK8,后面解释原因。
JDK下载地址:https://www.oracle.com/java/technologies/javase-downloads.html

2、通过 java -version 查看 JDK 版本。
可以看到我们的 JDK11 已经安装成功。

  1. zhibo-mac:JavaVirtualMachines zhibo$ java -version
  2. java version "11.0.6" 2020-01-14 LTS
  3. Java(TM) SE Runtime Environment 18.9 (build 11.0.6+8-LTS)
  4. Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.6+8-LTS, mixed mode)

3、启动测试代码。
在 Idea 中执行以下代码:代码的逻辑是向 list 中添加 1000 条数据,之后 sleep 1000 秒。

  1. package org.learn.jmap;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /** * @author zhibo * @date 2020-03-03 11:09 */
  5. public class JmapTest {
  6. public static void main(String[] args) {
  7. try {
  8. List list = new ArrayList();
  9. for (int i = 0; i < 1000; i++) {
  10. list.add(i);
  11. }
  12. Thread.sleep(1000 * 1000);
  13. } catch (InterruptedException e) {
  14. e.printStackTrace();
  15. }
  16. }
  17. }

4、通过 jps 命令查看 Java 进程 pid 和 名称。
本例中测试进程名为 JmapTest,它对应的 pid 为 32950。

  1. zhibo-mac:JavaVirtualMachines zhibo$ jps
  2. 27568 SALauncher
  3. 2099
  4. 32950 JmapTest
  5. 32951 Launcher
  6. 33002 Jps

5、通过 jmap -heap pid 打印 Java 堆的概要信息。
很不幸的是有报错了,提示使用 jhsdb jmap 代替 jmap。通过查找资料发现 JDK9 中新增了 jhsdb 命令,具体内容见:jhsdb

  1. zhibo-mac:JavaVirtualMachines zhibo$ jmap -heap 32950
  2. Error: -heap option used
  3. Cannot connect to core dump or remote debug server. Use jhsdb jmap instead

6、通过 jhsdb jmap --help 查找用法

  1. zhibo-mac:JavaVirtualMachines zhibo$ jhsdb jmap --help
  2. <no option> to print same info as Solaris pmap
  3. --heap to print java heap summary
  4. --binaryheap to dump java heap in hprof binary format
  5. --dumpfile name of the dump file
  6. --histo to print histogram of java object heap
  7. --clstats to print class loader statistics
  8. --finalizerinfo to print information on objects awaiting finalization
  9. --exe executable image name
  10. --core path to coredump
  11. --pid pid of process to attach

7、通过 jhsdb jmap --heap --pid 命令查看堆概要信息。
很不幸,又报错了。通过 field "_reserve_for_allocation_prefetch" not found in type ThreadLocalAllocBuffer 提示信息,大致可以判断, jhsdb 需要从 Java 进程中获取 _reserve_for_allocation_prefetch 字段,进而判定 JVM 版本,难道我的测试代码使用的是 JDK8 启动的,导致该问题的,接下来验证 JDK 版本。

  1. zhibo-mac:JavaVirtualMachines zhibo$ jhsdb jmap --heap --pid 32950
  2. Attaching to process ID 32950, please wait...
  3. Error attaching to process: java.lang.RuntimeException: can't determine target's VM version : field "_reserve_for_allocation_prefetch" not found in type ThreadLocalAllocBuffer
  4. sun.jvm.hotspot.debugger.DebuggerException: java.lang.RuntimeException: can't determine target's VM version : field "_reserve_for_allocation_prefetch" not found in type ThreadLocalAllocBuffer
  5. at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.setupVM(HotSpotAgent.java:436)
  6. at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:306)
  7. at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:141)
  8. at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.start(Tool.java:185)
  9. at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
  10. at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.main(JMap.java:176)
  11. at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.runJMAP(SALauncher.java:326)
  12. at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:455)
  13. Caused by: java.lang.RuntimeException: can't determine target's VM version : field "_reserve_for_allocation_prefetch" not found in type ThreadLocalAllocBuffer
  14. at jdk.hotspot.agent/sun.jvm.hotspot.runtime.VM.<init>(VM.java:337)
  15. at jdk.hotspot.agent/sun.jvm.hotspot.runtime.VM.initialize(VM.java:429)
  16. at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.setupVM(HotSpotAgent.java:432)
  17. ... 7 more

8、验证 JDK 版本。
果然我的测试代码使用的是 JDK8 启动的,见下图:
在这里插入图片描述
9、修改为 JDK11,重启测试代码。
10、通过 jhsdb jmap --heap --pid 命令成功获取到 Java 堆概要信息。

  1. zhibo-mac:JavaVirtualMachines zhibo$ jhsdb jmap --heap --pid 33146
  2. Attaching to process ID 33146, please wait...
  3. Debugger attached successfully.
  4. Server compiler detected.
  5. JVM version is 11.0.6+8-LTS
  6. using thread-local object allocation.
  7. Garbage-First (G1) GC with 10 thread(s)
  8. Heap Configuration:
  9. MinHeapFreeRatio = 40
  10. MaxHeapFreeRatio = 70
  11. MaxHeapSize = 4294967296 (4096.0MB)
  12. NewSize = 1363144 (1.2999954223632812MB)
  13. MaxNewSize = 2576351232 (2457.0MB)
  14. OldSize = 5452592 (5.1999969482421875MB)
  15. NewRatio = 2
  16. SurvivorRatio = 8
  17. MetaspaceSize = 21807104 (20.796875MB)
  18. CompressedClassSpaceSize = 1073741824 (1024.0MB)
  19. MaxMetaspaceSize = 17592186044415 MB
  20. G1HeapRegionSize = 1048576 (1.0MB)
  21. Heap Usage:
  22. G1 Heap:
  23. regions = 4096
  24. capacity = 4294967296 (4096.0MB)
  25. used = 5242880 (5.0MB)
  26. free = 4289724416 (4091.0MB)
  27. 0.1220703125% used
  28. G1 Young Generation:
  29. Eden Space:
  30. regions = 6
  31. capacity = 27262976 (26.0MB)
  32. used = 6291456 (6.0MB)
  33. free = 20971520 (20.0MB)
  34. 23.076923076923077% used
  35. Survivor Space:
  36. regions = 0
  37. capacity = 0 (0.0MB)
  38. used = 0 (0.0MB)
  39. free = 0 (0.0MB)
  40. 0.0% used
  41. G1 Old Generation:
  42. regions = 0
  43. capacity = 241172480 (230.0MB)
  44. used = 0 (0.0MB)
  45. free = 241172480 (230.0MB)
  46. 0.0% used

JDK的版本升级越来越快,对于每个版本新增的内容我们还是有必要了解一下,同步更新我们每个人的知识结构,否则会造成比较大的知识缺口的。文章内容仅代表个人观点,如有不正之处,欢迎批评指正,谢谢大家。

发表评论

表情:
评论列表 (有 0 条评论,96人围观)

还没有评论,来说两句吧...

相关阅读