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类的实例,再来说下它的三个字类
- InstanceMirrorKlass:用于表示java.lang.Class,Java代码中获取到的Class对象,实际上就是这个C++类的实例,存储在堆区,学名镜像类
- InstanceRefKlass:用于表示java.lang.ref.Reference类的子类
- InstanceClassLoaderKlass:用于遍历某个加载器加载的类
Java中的数组不是静态数据类型,是动态数据类型,即是运行期生成的,Java数组的元信息用ArrayKlass的子类来表示:
- TypeArrayKlass:用于表示基本类型的数组
- 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