HSDB(Hotspot Debugger),是一个内置的 JVM 工具,可以用来深入分析 JVM运行时内部状态。位于 JDK 安装目录下的 lib/sa-jdi.jar 中,启动命令:(一定要使用 sudo,否则后面输入 pid 后连接不上)
sudo java -cp sa-jdi.jar sun.jvm.hotspot.HSDB
打开界面后,依次点击 File -> Attach to HotSpot Process…
输入程序启动后的进程ID。
测试程序代码如下:
public abstract class A {
public void printMe() {
System.out.println("I love vim");
}
public abstract void sayHello();
}
public class B extends A {
@Override
public void sayHello() {
System.out.println("Hello, I am child B.");
}
}
public class TestDemo {
public static void main(String[] args) throws IOException {
A a = new B();
System.in.read();
System.out.println(a);
}
}
ps 或 jps 查看进程ID,输入后,依次点击
Tools -> Class Browser
找到 B 对象,内存地址如下:
B @0x00000007c0060418
然后依次点击 Tools -> Inspector
输入 B 的内存地址,可以显示 B 类的对象布局如下图所示:
可以看到虚方法表 vtable 长度为 7:
- 有5个是 Object 中可以继承的方法;(finalize equals toString hashCode clone)
- 1个是B 覆写的 sayHello() 方法;
- 1个是继承 A 的 printMe() 方法;
vtable 分配在 instanceKlass 对象实例的内存末尾, instanceKlass 在 64位系统的大小为 0x1B8,因此 vtable 的起始地址等于 instanceKlass 的内存首地址(0x7c0060418)加上 0x1B8,等于 0x7C00605D0。
依次点击 Windows -> Console,输入 mem 命令查看实际的内存分布。mem 命令需要2个参数,一个是起始地址,一个是长度。
mem 0x7C00605D0 7
可以看到前5个地址分别与 Object 类的5个方法一一对应:
然后是 B 类覆写的 sayHello() 方法
A类继承的 printMe() 方法