0
点赞
收藏
分享

微信扫一扫

Klass模型与类加载的详细机制

勇敢的趙迦禾 2022-02-15 阅读 45

klass模型是jvm中的数据类型 这个数据类型表示的是一个java类 java语言是在jvm中运行而jvm是不认识java代码的我们使用javac编译的class文件jvm是不认识的 所以有一个类加载的动作 这个动作就是把class字节码拼装成一个klass类型 这个klass类型是c++中的一个类 klass里面有java类中的所有信息比如它的属性 方法 修饰符等成为类的元信息 这些信息放在元空间中 通过下面的klass类的继承关系图可以看出
在这里插入图片描述
metaspace中文意思就是元空间 meatadata中文意思元数据
klass是c++中表示java类的数据类型 klass下面又分为普通类型与数组类型
普通类型就是我们自己定义的java类一个java类就是一个instanceKlass这个东西是放在方法区中 然后一个java类的对象就是一个instanceMirrorKlass它是放在堆中
而数组类型又分为两种TypeArrayKlass用来表示一个基本数据类型的数组 ObjArrayKlass表示一个引用类型的数组 数组是一个动态的数据类型 数组会在jvm运行它的那一刻进行创建 否则它没有实体

类的加载过程
类的加载由五个部分加载、验证、准备、解析、初始化

加载就是把硬盘上的class文件加载到内存 然后把它二进制流中的数据读取成一个klass 这时的加载只是加载了java类的信息 不包含属性

验证就是验证这个class符不符合要求

准备这一步把静态变量赋初值
在这里插入图片描述
上面是静态变量的默认值 静态变量会存放在class对象中 然后准备这一步的作用
如果在java代码中写static int a; 它不会在clinit中把这个静态变量赋值的操作写进去 clinit是编译后的静态代码块一个java类只会生成一个静态代码块也就是只会生成一次clinit 生成一次之后只会往clinit中按着顺序往里添加被static修饰的代码 像a这样的写法如果没有准备操作就不会往clinit中添加然后a就会被丢失 static int b = 0;这样写 clinit中就会有b=0这样的代码 这个clinit会在初始化的时候调用 在class加载的时候只加载了类信息属性没有被加载 而static是类加载的时候就会被创建可以直接用类名点属性名 看类的加载机制这5步只有在准备与初始化执行静态方法的时候才有赋值的动作 而初始化执行的静态代码块是在java编译的时候生成 它生成的机制是静态属性必须有赋值操作 所以说如果没有准备操作a就会被丢失 如果在类加载的过程中没有赋值的操作就不会放到klass中 放不到klass中也就意味着在java类加载到堆中的时候也是什么变量都没有的 准备这一步操作就是为了可以把静态变量放到klass中
如果被final修饰,在编译的时候会给属性添加ConstantValue属性,准备阶段直接完成赋值,即没有赋初值这一步

解析

解析就是把符号引用变为直接引用 比如java代码编制之后会把 int a = 3 这个3会写到常量池 常量池会给3分配一个地址 而符号引用就是a = 3在常量值中的地址,直接引用是指向运行时常量池 运行时常量池就是把常量池中的3变成了存放3的内存地址 然后就成了a=3的内存内地这样叫直接引用

初始化

执行静态代码块 完成静态变量的赋值

举报

相关推荐

0 条评论