package org.example.classLoading;
import java.io.IOException;
/**
* 演示多态原理,注意加上下面的 JVM 参数,禁用指针压缩
* -XX:-UseCompressedOops -XX:-UseCompressedClassPointers
*/
public class PolymorphicTest {
public static void test(Animal animal){
animal.eat();
}
public static void main(String[] args) throws IOException {
test(new Cat());
test(new Dog());
System.in.read();
}
}
abstract class Animal {
public abstract void eat();
@Override
public String toString() {
return "我是"+this.getClass().getSimpleName();
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("啃骨头");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("吃鱼");
}
}
停在 System.in.read() 方法上,这时运行 jps 获取进程 id:4268
PS F:\software\IDEA\JavaProjects\JvmTest> jps
5956 Launcher
10956
17596 Jps
4268 PolymorphicTest
进入 JDK 安装目录,执行
F:\software\Java\jdk1.8.0_333>java -cp ./lib/sa-jdi.jar sun.jvm.hotspot.HSDB
进入图形界面 attach 进程 id
打开 Tools -> Find Object By Query
输入 select d from org.example.classLoading.Dog d 点击 Execute 执行
点击 0x0000020f086acd98 可以看到对象的内存结构。此对象没有任何属性,因此只有对象头的 16 字节。
前 8 字节是 MarkWord,后 8 字节就是对象的 Class指针 。目前看不到 Class对象 的实际地址
方式一:连接前面第五节
可以通过 Windows -> Console 进入命令行模式,执行下面命令查找对象中word的内存地址
mem 0x0000020f086acd98 2
命令中有两个参数。参数 1 是对象地址,参数 2 是查看 2 行(即 16 字节)
结果中第二行 0x0000020f373d4128 即为 Class对象 的内存地址
方式二
Tools -> Class Browser 输入 Dog 查找,可以得到相同的结果:0x0000020f373d4128
Alt+R 进入 Inspector 工具,输入刚才的 Class对象 内存地址,看到如下界面
无论通过哪种方法,都可以找到 Dog Class对象 内存地址。发现 vtable 长度为 6,意思就是 Dog 类有 6 个虚方法(多态相关的。final,static 不会列入)
那么这 6 个方法都是谁呢?从 Class 的起始地址开始算,偏移 0x1b8 就是 vtable 的起始地址,进行计算得到:
0x0000020f373d4128
1b8 +
--------------------
0x0000020f373d42e0
通过 Windows -> Console 进入命令行模式,执行下面命令。得到了 6 个虚方法的入口地址
mem 0x0000020f373d42e0 6
通过 Tools -> Class Browser 查看每个类的方法定义,比较可知:
Dog - public void eat() @0x0000020f373d40d0
Animal - public java.lang.String toString() @0x0000020f373d36a8
Object - protected void finalize() @0x0000020f36fd1b10
Object - public boolean equals(java.lang.Object) @0x0000020f36fd15e8
Object - public native int hashCode() @0x0000020f36fd1540
Object - protected native java.lang.Object clone() @0x0000020f36fd1678
当执行 invokevirtual 指令时