JVM基础之klass模型

486 阅读4分钟

简介

本篇文章主要是以“认识”为主,所谓的认识就是,你不需要关注里边的细节,只需要大概了解,”认识一下“就好

klass是什么

没有拼错

首先要声明的是,就是klass不是class没有拼错

先建立一个概念

我们的java代码要想运行起来,首先要被编译成class字节码,再把class字节码加载到jvm虚拟机中,由jvm进一步处理。jvm又是什么呢?, 大家现在只需要两点

  • 它是由c++编写的
  • c++是面向对象的语言

image.png

设身处地想一个问题

如果此时让你用java,创造一门编程语言,姑且叫它,“haha”(放心,我们只是假设,并不是真的去设计,大可不必担心自己没学过编译原理),

实现一个超简单的功能

haha语言的语法如下

image.png

我们设想一下该如何实现:

  • 首先一定是读取haha文件,
  • 其次是解析出 hlass类名,及function(方法)
  • 解析好之后我们肯定还要吧类的信息记录下来,比如类名(因为记录下来才能再调用whoAmI的时候把类名打印出来)

划重点: 把类的信息记录下来

如何记录类的信息呢 ?

很简单如果在java中,我们一定是这样做

public class HaHaHlassInfo {

    /**
     * 记录haha类的类名
     */
    private String hlassName;

    /**
     * 记录haha类中所有的方法
     */
    private List HahaFunctions;
    
    
}

没错,java是面向对象的语言,在面向对象语言的世界中一切皆对象,所以我们用一个对象(类)来保存haha的类信息

回到jvm

还记得我们刚刚讲的吗?,c++也是面向对象的语言,正如你所想的klass就是c++中用来描述java类信息的类。准确的说是基类(父类)

一探究竟

我们口说无凭,看不见摸不着的东西总是抽象的,下面我们就来看一看具体的东西

非数组类

我们先看一看java中的非数组类,在c++中对应的klass是什么样子的?

如何看

这就要介绍一款,jdk自带的工具hsdb了,它能看到我们的java对象在JVM里是什么样子

下面开始演示

第一步

运行我们的java程序

程序很简单,写一个read()方法让方法不要结束

image.png

第二步

查看进程号

(3345)

image.png

第三步

启动hsdb

  • 进入jdk的lib目录

image.png

  • 执行
java -cp sa-jdi.jar sun.jvm.hotspot.HSDB

image.png

  • attach到进程

image.png

  • 输入进程号

image.png

  • 选择类浏览

image.png

  • 然后就能看到我们的java类的内存地址了

image.png

记下这个内存地址(也就是0x00000000100061dd0)

  • 选择inspector

image.png

  • 输入内存地址

image.png

第四步

到这我们就可以看到有个叫instanceKlass的“东西”

instanceKlass与klass是什么关系?

我们在前面说了,klass相当于基类,那么instanceKlass就是子类喽

我们看一眼代码

image.png

通过代码也清楚的看到InstanceKlass继承了Klass

image.png

非数组类看得差不多了,再来看看数组类

基本类型数组

看看它在内存里什么样子

比如 int bool

  • 准备好java代码

image.png 在代码中我们创建一个integer类型的数组

  • 同样的方法attach到java进程

image.png

  • 观察main方法的栈内存

因为数组是运行时生成的类型(你想想java中数组是不是没有对应的类,而是用 “类型[]” 表示),所以我们不能通过类浏览来找到它,而是通过查看main的栈内存

image.png

  • 找到在内存中的地址

可以看到这个地有一个符号 “[I” 这个就是int数组的标识,我们记下它的内存地址

image.png

  • 到inspector中检索

可以看到与之对应的是TypeArrayKlass image.png

看看代码

TypeArrayKlass继承了ArrayKlass

image.png

ArrayKlass继承了Klass image.png

完善一下类图

image.png

非基本类型数组

看完了基本类型数组再来看看非基本类型数组

看看它在内存中是什么样子

方法与基本类型数组一样,我们直接看结果

image.png

可以看到它的类型是ObjArrayKlass

ObjArrayKlass同样继承了ArrayKlass类

image.png

完善一下类图

image.png

最后看一眼InstanceMirrorKlass

保证知识的完整性我们搂一眼InstanceMirrorKlass

image.png

顾名思义“镜像类”,它是什么呢?

它对应的就是我们java中的Class类

image.png

最后来一张完整的类图,和他们在内存的位置

image.png

到这java中所有类型在c++中对应的类我们就介绍完了