JDK 8之后如何在HotSpot中查看instanceKlass及ConstantPoolCache?
如何在JDK 8+的HotSpot中查看instanceKlass
嘿,这个问题确实戳中了JDK8切换到Metaspace后,不少老HSDB用户的痛点——原来PermGen里的instanceKlass结构变了,老工具直接用会找不到关键字段比如ConstantPoolCache。我整理了几个靠谱的方案,亲测在JDK8到JDK21都能用:
1. 使用兼容JDK8+的新版HSDB
JDK8自带的HSDB其实已经适配了Metaspace,只是很多人没找对打开方式:
- 启动命令:在终端执行
java -cp $JAVA_HOME/lib/sa-jdi.jar sun.jvm.hotspot.HSDB(Windows下把$JAVA_HOME换成你的JDK安装路径) - 查看instanceKlass步骤:
- 点击
File -> Attach to Process,选择你要调试的JVM进程ID - 打开
Tools -> Class Browser,搜索目标类(比如java.lang.String) - 右键选中类,点击
Inspect InstanceKlass,在弹出的窗口里就能看到完整的instanceKlass结构,包括_constant_pool字段,展开它就能找到_cache(也就是ConstantPoolCache)
- 点击
2. 用JDK9+自带的jhsdb工具
JDK9及以后把HSDB整合进了jhsdb命令,用起来更方便,支持图形和命令行两种模式:
- 图形界面模式:执行
jhsdb hsdb --pid <你的进程ID>,后续操作和上面的HSDB完全一致 - 命令行模式(适合服务器环境):
- 执行
jhsdb clhsdb --pid <你的进程ID>进入交互式命令行 - 输入
find <类全限定名>找到对应instanceKlass的内存地址,比如find java.util.ArrayList - 输入
inspect <地址>查看完整结构,比如inspect 0x7f9b12345678,直接就能看到ConstantPoolCache等字段
- 执行
3. 程序化查看:使用HotSpot Serviceability Agent (SA) API
如果需要批量或者自动化查看instanceKlass信息,可以写代码调用SA的API:
import sun.jvm.hotspot.HotSpotAgent; import sun.jvm.hotspot.runtime.InstanceKlass; import sun.jvm.hotspot.runtime.VM; import sun.jvm.hotspot.tools.Tool; public class InstanceKlassInspector extends Tool { @Override public void run() { VM vm = VM.getVM(); // 替换成你要查看的类全限定名 InstanceKlass klass = (InstanceKlass) vm.getSystemDictionary().find("java.lang.String"); System.out.println("InstanceKlass 内存地址: 0x" + Long.toHexString(klass.getAddress())); System.out.println("ConstantPoolCache 地址: 0x" + Long.toHexString(klass.getConstantPool().getCache().getAddress())); // 可以通过klass的getter方法获取更多字段,比如类名、访问标志等 System.out.println("类名: " + klass.getName().asString()); } public static void main(String[] args) { InstanceKlassInspector inspector = new InstanceKlassInspector(); // 运行时需要传入目标进程ID作为参数 inspector.execute(args); } }
- 编译和运行注意事项:
- 编译时要依赖SA的jar包:
javac -cp $JAVA_HOME/lib/sa-jdi.jar InstanceKlassInspector.java - 运行时需要足够权限(Linux下加sudo),并指定进程ID:
java -cp .:$JAVA_HOME/lib/sa-jdi.jar InstanceKlassInspector <进程ID>
- 编译时要依赖SA的jar包:
关键注意事项
- 版本匹配:必须确保HSDB/jhsdb/SA API的版本和目标JVM完全一致,否则会因为Metaspace结构差异导致解析失败
- 权限问题:调试本地进程需要足够权限,远程调试还要配置相关参数
- 禁用Attach机制:如果目标JVM启动时加了
-XX:+DisableAttachMechanism,就无法用这些工具连接了
内容的提问来源于stack exchange,提问作者Q_SJ
相关产品推荐
相关产品推荐

