JVM之Classfile文件解析

JVM之Classfile文件解析

1.魔数

我们在学习JVM时通常会从class文件入手。

那么魔数就是我们认识的第一个东西。
每个Class文件的头4个字节称为魔数(Magic Number)
唯一作用是用于确定这个文件是否为一个能被虚拟机接受的Class文件。
Class文件魔数的值为0xCAFEBABE。如果一个文件不是以0xCAFEBABE开头,那它就肯定不是Java class文件。
很多的文件存储标准中都使用魔数来识别文件的身份。 譬如图片格式.gif 或 jpeg等在文件的头部都存有魔数,使用魔数而不是文件的扩展名称来判断 ,这种情况是处于安全的考虑。

2.class文件版本号

紧挨着魔术的4个字节表示class的文件的版本号 版本号:
1.次版本号 --minor_version 前2个字节用于表示次版本号 例如:00 00
2.主版本号 --major_version 后2个字节用于表示主版本号 例如: 00 34
Java的版本号是从45开始的。如果class的版本号超过虚拟机的版本 会被拒绝执行。
JDK1.2 ----0X002E 46
JDK1.3 ----0X002F 47
JDK1.4 ----0X0030 48
JDK1.5 ----0X0031 49
JDK1.6 ----0X0032 50
JDK1.7 ----0X0033 51
JDK1.8 ----0X0034 52

3. constant_pool_count(常量池个数)

版本号后面是常量池的个数,占两个字节。
constant_pool_count 从1开始计数的。 class文件结构中只有常量池的容量计数是从1开始的。第0项腾出来满足后面某些指向常量池的索引值的数据,在特定的情况下需要表达“不引用任何一个常量池项目” 把索引值的第0项留给JVM自己用。

4. constant_pool(常量池)

长度为 constant_pool_count-1

常量池详细解析常量类型总共有18个编号的常量类型。
constant_pool的具体内容:索引,标志tag,类型
1.编号1: CONSTANT_UTF8_INFO
Tag1 ------占用一个空间字节
Length: utf-8字符串占用的字节数
Bytes 长度为length字符串
用于表示utf-8的编码的字符串

3.编号3 CONSTANT_integer_info
Tag3
Bytes 4个字节 Big_Endian(高位在前) 存储int类型的值

4.编号4 CONSTANT_float_info
Tag4
Bytes 4个字节 Big_Endian(高位在前) 存储float类型的值

5.编号5 CONSTANT_long_info
Tag5
Bytes 8个字节 Big_Endian(高位在前) 存储long类型的值

6.编号6 CONSTANT_double_info
Tag6
Bytes 8个字节 Big_Endian(高位在前) 存储double类型的值

7.编号7 CONSTANT_Class_info
Tag7
Index 2个字节 指向类的全限定名的项的索引
类和接口符号引用

8.编号8 CONSTANT_String_info
Tag8
Index 2个字节 指向字符串的字面量的索引

9.编号9 CONSTANT_Fieldref_info
Tag9
Index 2个字节 指向声明字段的类或接口的描述符 CONSTANT_Class_info的索引项
Index 2个字节 指向字段描述符CONSTANT_NameAndType的索引项
字段的符号引用

10.编号10 CONSTANT_Methodref_info
Tag10
Index 2个字节 指向声明字段的类或接口的描述符 CONSTANT_Class_info的索引项
Index 2个字节 指向字段描述符CONSTANT_NameAndType的索引项
类中方法的符号引用

11.编号11 CONSTANT_InterfaceMethodref_info
Tag11
Index 2个字节 指向声明字段的类或接口的描述符 CONSTANT_Class_info的索引项
Index 2个字节 指向字段描述符CONSTANT_NameAndType的索引项
接口中方法的符号引用

12.编号12 CONSTANT_NameAndType
Tag12
Index 2个字节 指向该字段或方法名称常量项的索引
Index 2个字节 指向该字段或方法描述符常量项的索引
字段或方法的符号引用

15.编号15 CONSTANT_MethodHandler_info
Tag15
Reference_kind 1个字节 1-9之间的一个值 决定了方法句柄的类型。方法句柄类型的值表示方法句柄的字节码行为
Reference_index 2个字节 对常量池的有效索引。
表示方法句柄

16.编号16 CONSTANT_MethodType_info
Tag16
Descriptor_index 2个字节 指向UTF8_info 结构表示的方法描述符

18.编号18 CONSTANT_InvokeDynamic_info
Tag18
Bootstrap_method_attr_index: 2个字节 当前class文件中引导方法表的bootstrap_methods[] 数组的有效索引
Name_and_type_index: 2个字节 指向NameAndType_info 表示方法名和方法描述符。
表示动态方法的调用点。

5.access_flag

用于表示对该类或接口的访问权限以及该类或接口的属性

在这里插入图片描述

6.Method属性

Method属性包含三个字段值

名称access_flag 类型u2 数量1个attributes_count 1

名称 name_index 类型u2 数量1个 attribute_info attributes ----attributes_count

名称 descriptior_index 类型u2 数量1个

descriptior_index

参数列表(参数类型) 后-返回值
void m() 等同于 ()V
String toString() ->()Ljava/lang/String;
Long pos(int[] arr1,int arr2,long length) ->([IIJ)J

在这里插入图片描述

7.Fields属性

名称access_flag 类型u2 数量1个attributes_count 1

同method属性

名称 name_index 类型u2 数量1个 attribute_info attributes ----attributes_count

名称 descriptior_index 类型u2 数量1个

同method属性值。

关于attributes_count 附加属性的数量

关于 attributes 附加属性

第9个常量池LineNumberTable 是在后面要使用的常量的名字,在code当中被引用到。

8.双亲委派

Class文件通过自定义的classloader进行加载,如果他没有加载,那么则委托它的父加载器appclassloader 加载, appclassloader 判断是否为本地加载 如果有则直接加载,如果没有则继续向上委托,直到顶层的加载器bootstrapClassLoader,但是当顶层的加载器,也没有加载,就会向下委托,当所有的下级加载器都没有加载那么则抛出异常 classNotFound 异常,如果下级加载器能够加载,那么就由下级加载器进行加载。

双亲:指的有一个从子到父的过程 又有一从父到子的过程

委派:自己不想做的事情 委托别人去完成

向上委派的时候 父加载器都是到 Cache中取寻找

可以把这个缓存理解成是一个list或者是一个数组。

面试题 为什么要去使用双亲委派?

\1. 防止加载同一个class文件,保证数据的安全

\2. 保证核心的class文件不被篡改,即使被篡改了也不会加载,即使被加载也不会是同一个class对象 为了保证class的执行安全。

这部分代码是被写死的。

9.如何打破双亲委派

去重写Classloader中的loadClass方法 而不是findClass方法 这个时候就能够打破双亲委派的机制。

什么时候需要打破需要去打破双亲委派的机制:

在JDK1.2版本之前 要自定义classloader的话 必须要重写loadClass方法

在一个线程中设定自己的线程的上下文的加载器对象 ThreadContextClassLoader 可以实现基础调用实现类的代码, 通过thread.setContextClassLoader 来设定。

模块化的 热部署 热启动

像osgi和tomcat 都有自己的模块指定classloader,可以加载同一个类库的不同版本的对象,目前这个方式用的比较多。

Tomcat中 Webapplication 对象是可以存在多个的,有两个Webapplication 被加载,但是他们的版本不同,这种情况下可以打破双亲委派的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值