jvm

JVM之Klass模型

Klass模型

Posted by HuangCanCan on August 22, 2020

Klass模型

补充:

OOP-Klass模型

OOP 指的是 Ordinary Object Pointer (普通对象指针),它用来表示对象的实例信息,看起来像个指针实际上是藏在指针里的对象。而 Klass 则包含元数据和方法信息,用来描述Java类。

klass是类

oop klass是类的内存地址(指针)

Klass :包含元数据和方法信息,用来描述Java类。

class 和 klass区别:

class:Java类,Java代码

klass:Java类在JVM的存在形式,c++代码

在JDK8中,Java的每个类,在JVM中,都有一个对应的Klass类实例与之对应,存储类的元信息如:常量池、属性信息、方法信息……

klass模型类的继承结构:

从继承关系上也能看出来,类的元信息是存储在原空间的。

普通的Java类在JVM中对应的是instanceKlass类的实例,再来说下它的三个字类

  1. InstanceMirrorKlass:用于表示java.lang.Class,Java代码中获取到的Class对象,实际上就是这个C++类的实例,存储在堆区,学名镜像类
  2. InstanceRefKlass:用于表示java.lang.ref.Reference类的子类
  3. InstanceClassLoaderKlass:用于遍历某个加载器加载的类

Java中的数组不是静态数据类型,是动态数据类型,即是运行期生成的,Java数组的元信息用ArrayKlass的子类来表示:

  1. TypeArrayKlass:用于表示基本类型的数组
  2. ObjArrayKlass:用于表示引用类型的数组

可以通过 Source Insight 工具查看openJDK源码。

InstanceKlass

MetadataObj:是所有Klass 的基类,存储在元空间

—- Metadata

——– klass

———— InstanceKlass:每个java类都对应一个InstanceKlass ,存储类的元信息

——————– InstanceMirrorKlass:镜像类,存储Class对象,在堆区

——————– InstanceRefKlass:引用

——————– InstanceClassLoaderKlass

对象的内存结构中有一个klass pointer,klass其实就是InstanceKlass及其子类

类加载器将.class文件加载进系统,将.class文件解析,生成的是什么?类的元信息在JVM中如何存储?

查看InstanceKlass:

// 运行的Java代码
public class Test_1 {
    public static void main(String[] args) {
        while (true) ;
    }
}

通过jps命令查看Test_1进程ID = 23304

通过HSDB工具查看

HSDB(Hotspot Debugger),JDK自带的工具,用于查看JVM运行时的状态

HSDB位于D:\Program Files\Programmer\java\jdk1.8.0_202\lib里(jdk安装路径下的lib)

# 启动HSDB
java -cp sa-jdi.jar sun.jvm.hotspot.HSDB

启动后的HSDB:

点击Attach to HotSpot process 输入Test_1的进程ID 23304

输入进程ID后:

点击Class Browser:查这个进程的所有类

可以看到Test_1的内存地址:

点击Inspector,输入Test_1的内存地址 0x0000000100060828

可以看到InstanceKlass

在Java中是Test_1类,但在JVM中是一个InstanceKlass。一个Java类对应jvm中的一个InstanceKlass

ArrayKlass

———— ArrayKlass:存储数组类的元信息

Java中的数组是动态数据类型。

​ 1.静态数据类型,jvm内置的八种数据类型

​ 2.动态数据类型,运行时动态生成的

字节码指令手册参考

如何证明Java中的数组是动态数据类型?

如下图,将Java代码build后,通过 jclasslib 字节码查看器(通过idea的插件库搜索安装)查看。安装好jclasslib插件后,点击 idea 的 View —–Show Bytecode With jclasslib

基本类型数组:

是 newarray

newarray 代表:创建一个指定原始类型(如int, float, char…)的数组,并将其引用值压入栈顶

引用数据类型:

是anewarray

anewarray 代表:创建一个引用型(如类,接口,数组)的数组,并将其引用值压入栈顶

——————TypeArrayKlass:基本类型的数组在JVM中的存在形式

——————ObjArrayKlass:引用类型的数组在JVM中的存在形式

查看ArrayKlass:

main线程的堆栈中查看

public class Test_1 {

    public static void main(String[] args) {
        int[] arr = new int[1];

        Test_1[] arr2 = new Test_1[1];
        
        while (true) ;
    }
}

先运行上述Java代码,通过jps命令查看Test_1进程ID = 15956

然后,启动HSDB(不知道HSDB如何启动,请往前面查看),步骤参考举例证明InstanceKlass