hsdb不显示裸二进制,而是按jvm的oop/klass模型解析内存:inspect展示字段偏移与指针值,scanoops定位对象并结合universe/findpc验证gc区域归属,class browser显示字段线性布局及offset,需注意压缩指针解压与对齐填充。

HSDB 不能直接显示“二进制布局”(比如逐字节 dump 出 01010101),它展示的是 HotSpot 内部的 Oop/Klass 抽象结构,但通过 inspect、scanoops、Class Browser 等命令,你能准确定位字段偏移、指针值、内存区域归属——这比裸二进制更贴近 JVM 实际语义。
用 inspect 查看对象头与实例数据的原始内存映射
HSDB 的 inspect 命令输出的是对象在内存中被 JVM 解析后的结构视图,不是 hex dump。它会明确标出 _mark、_metadata._compressed_klass、字段名及对应地址,相当于把内存按 JVM 的 Oop 模型“翻译”出来。
- 运行
inspect 0x00000000ff670190后看到的a: Oop for java/lang/Integer @ 0x00000000ff62e970,说明字段a是一个引用,其值(即存储的地址)是0x00000000ff62e970,不是字段内容本身 -
_metadata._compressed_klass显示的是压缩后的类指针(如果启用了 -XX:+UseCompressedClassPointers),真实 Klass 地址需解压计算;不压缩时直接显示完整 8 字节地址 - 字段顺序不一定和源码声明顺序一致:JVM 会按宽度重排(long/double → int → short/char → byte/boolean → 引用),
Class Browser工具能直观看到每个字段的 offset(如a在 offset 12)
用 scanoops 定位对象起始地址并验证内存区域归属
对象物理地址只是一串数字,关键是要确认它落在哪个 GC 区(Eden / From / Old)、是否在 TLAB 内、是否被压缩指针影响。这必须结合 universe 和 findpc 使用。
-
universe输出里会列出 Eden、From、Old 的起止地址(如eden [0x00000000ff600000,0x00000000ff680030,0x00000000ff8b0000)),这是后续扫描的合法范围 -
scanoops 0x00000000ff600000 0x00000000ff680030 java.lang.String扫出的每个地址,都要用findpc 0x00000000ff670190验证是否真在 Eden 内——避免误扫到元空间或栈内存 - 若 JVM 启用了 -XX:+UseCompressedOops,所有堆内对象引用都是 4 字节整数,但
inspect会自动解压显示为 8 字节逻辑地址;你不能直接拿scanoops结果当“原始二进制”去 hex 编辑器里查
用 Class Browser 查字段偏移,理解实例数据如何线性排布
字段在对象内存中是连续存放的(除去对齐填充),Class Browser 显示的 offset 就是从对象起始地址开始的字节偏移量。这是最接近“物理布局”的可验证信息。
- 打开
Tools → Class Browser,输入类名(如Test2),它列出所有字段及其offset(例如int x在 offset 12,Object ref在 offset 16) - 再用
inspect查看该对象地址,对比字段值是否出现在对应 offset:比如ref字段值是0x00000000ff62ea10,那在0x00000000ff670190 + 16处的 4 或 8 字节内存内容就该等于这个值(取决于是否压缩) - 注意对齐填充:如果字段总长不是 8 的倍数,JVM 会在末尾补 0~7 字节,这部分不会显示在
Class Browser中,但会影响下一个对象的起始位置
真正难的不是找地址或看字段,而是区分“指针值”和“指针指向的内容”——inspect 显示的 Oop for java/lang/Integer @ 0x... 是引用字段的值(即地址),而那个地址处的内容要另起一次 inspect 才能看到。漏掉这一层跳转,就永远停留在表层。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











