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