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

一、问题描述

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

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

package org.learn.jmap;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zhibo
 * @date 2020-03-03 11:09
 */
public class JmapTest {

    public static void main(String[] args) {
        try {
            List list = new ArrayList();
            for (int i = 0; i < 1000; i++) {
                list.add(i);
            }
            Thread.sleep(1000 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

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

zhibo-mac:JavaVirtualMachines zhibo$ jps
32848 Jps
27568 sun.jvm.hotspot.SALauncher
2099 
32844 Launcher
32845 JmapTest
zhibo-mac:JavaVirtualMachines zhibo$ 

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

zhibo-mac:JavaVirtualMachines zhibo$ jmap -heap 32845
Attaching to process ID 32845, please wait...
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
	at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal$BsdDebuggerLocalWorkerThread.execute(BsdDebuggerLocal.java:169)
	at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.attach(BsdDebuggerLocal.java:287)
	at sun.jvm.hotspot.HotSpotAgent.attachDebugger(HotSpotAgent.java:671)
	at sun.jvm.hotspot.HotSpotAgent.setupDebuggerDarwin(HotSpotAgent.java:659)
	at sun.jvm.hotspot.HotSpotAgent.setupDebugger(HotSpotAgent.java:341)
	at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:304)
	at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140)
	at sun.jvm.hotspot.tools.Tool.start(Tool.java:185)
	at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
	at sun.jvm.hotspot.tools.HeapSummary.main(HeapSummary.java:49)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.tools.jmap.JMap.runTool(JMap.java:201)
	at sun.tools.jmap.JMap.main(JMap.java:130)
Caused by: sun.jvm.hotspot.debugger.DebuggerException: Can't attach symbolicator to the process
	at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.attach0(Native Method)
	at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.access$100(BsdDebuggerLocal.java:65)
	at sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal$1AttachTask.doit(BsdDebuggerLocal.java:278)
	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 已经安装成功。

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

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

package org.learn.jmap;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zhibo
 * @date 2020-03-03 11:09
 */
public class JmapTest {

    public static void main(String[] args) {
        try {
            List list = new ArrayList();
            for (int i = 0; i < 1000; i++) {
                list.add(i);
            }
            Thread.sleep(1000 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

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

zhibo-mac:JavaVirtualMachines zhibo$ jps
27568 SALauncher
2099 
32950 JmapTest
32951 Launcher
33002 Jps

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

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

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

zhibo-mac:JavaVirtualMachines zhibo$ jhsdb jmap --help
    <no option>	to print same info as Solaris pmap
    --heap	to print java heap summary
    --binaryheap	to dump java heap in hprof binary format
    --dumpfile	name of the dump file
    --histo	to print histogram of java object heap
    --clstats	to print class loader statistics
    --finalizerinfo	to print information on objects awaiting finalization
    --exe	executable image name
    --core	path to coredump
    --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 版本。

zhibo-mac:JavaVirtualMachines zhibo$ jhsdb jmap --heap --pid 32950
Attaching to process ID 32950, please wait...
Error attaching to process: java.lang.RuntimeException: can't determine target's VM version : field "_reserve_for_allocation_prefetch" not found in type ThreadLocalAllocBuffer
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
	at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.setupVM(HotSpotAgent.java:436)
	at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:306)
	at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:141)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.start(Tool.java:185)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.main(JMap.java:176)
	at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.runJMAP(SALauncher.java:326)
	at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:455)
Caused by: java.lang.RuntimeException: can't determine target's VM version : field "_reserve_for_allocation_prefetch" not found in type ThreadLocalAllocBuffer
	at jdk.hotspot.agent/sun.jvm.hotspot.runtime.VM.<init>(VM.java:337)
	at jdk.hotspot.agent/sun.jvm.hotspot.runtime.VM.initialize(VM.java:429)
	at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.setupVM(HotSpotAgent.java:432)
	... 7 more

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

zhibo-mac:JavaVirtualMachines zhibo$ jhsdb jmap --heap --pid 33146
Attaching to process ID 33146, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 11.0.6+8-LTS

using thread-local object allocation.
Garbage-First (G1) GC with 10 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 4294967296 (4096.0MB)
   NewSize                  = 1363144 (1.2999954223632812MB)
   MaxNewSize               = 2576351232 (2457.0MB)
   OldSize                  = 5452592 (5.1999969482421875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 1048576 (1.0MB)

Heap Usage:
G1 Heap:
   regions  = 4096
   capacity = 4294967296 (4096.0MB)
   used     = 5242880 (5.0MB)
   free     = 4289724416 (4091.0MB)
   0.1220703125% used
G1 Young Generation:
Eden Space:
   regions  = 6
   capacity = 27262976 (26.0MB)
   used     = 6291456 (6.0MB)
   free     = 20971520 (20.0MB)
   23.076923076923077% used
Survivor Space:
   regions  = 0
   capacity = 0 (0.0MB)
   used     = 0 (0.0MB)
   free     = 0 (0.0MB)
   0.0% used
G1 Old Generation:
   regions  = 0
   capacity = 241172480 (230.0MB)
   used     = 0 (0.0MB)
   free     = 241172480 (230.0MB)
   0.0% used

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

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值