一、 java class 字节码概述以及Java字节码结构

java类型识别:Java类是编译器生成字节码有其特定的组织规律,Java虚拟机在加载类时,对编译期生成的字节码信息按照固定的格式进行解析,一步一步解析出来字节码中所存在的类型结构信息,从而在运行期完全还原出原始的Java类的全部结构  。

class的字节概述:每一个Java类被编译之后生成一个对应的.class 字节码文件,需要明白jvm加载java类的原理,首先需要知道java类被编译之成的.class格式文件结构。下面通过实例代码来描述字节码的组成格式。

 

一、idea中实例查看

1、首先我们在ida中创建一个项目,demo,然后  编译一下,如下图所示:

一、 java class 字节码概述以及Java字节码结构

以上文件就是一个spring boot 项目的一个程序入口带有main 方法的类

2、查看编译之后的字节码文件:通过在ida中安装HexView插件查看(HexView使用,请翻看另一篇安装HexView),

一、 java class 字节码概述以及Java字节码结构

3、通过反编译之后的class文件,做如下对比:

一、 java class 字节码概述以及Java字节码结构一、 java class 字节码概述以及Java字节码结构

通过以上两个文件前后对比,我们发现编译后的文件,自动加上了默认的构造该函数 

二、class 文件构成基础

1、class文件构成基础

在class字节码文件中,数据都是以二进制流的形式存储。字节流都安装规定的顺序排序,字节码之间不存在任何空袭,对于超过8位的数据,按照Big-Endian(大端)的顺序存储,即:低地址存放高有效字节,反之小端(little endian):低字节存放地有效字节

2、class 文件的10个组成结构

  class字节码文件采用类似c语言的结构体存储数据,主要分以下

(1),我们来说明一下:class文件只有两种数据类型:无符号数。如下表所示

数据类型 定义 说明
无符号 无符号数可以用来描述数字、索引引用、数量值或按照utf-8编码构成的字符串值。 其中无符号数属于基本的数据类型。
以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节
表是由多个无符号数或其他表构成的复合数据结构。 有的表都以“_info”结尾。
由于表没有固定长度,所以通常会在其前面加上个数说明。

(2)、以下就是字节码结构表

类型 名称 说明 长度(字节)
u4 magic 魔数,识别Class文件格式 4
u2 minor_version 副版本号 2
u2 major_version 主版本号 2
u2 constant_pool_count 常量池计算器 2
cp_info constant_pool 常量池 n
u2 access_flags 访问标志 2
u2 this_class 类索引 2
u2 super_class 父类索引 2
u2 interfaces_count 接口计数器 2
u2 interfaces 接口索引集合 2
u2 fields_count 字段个数 2
field_info fields 字段集合 n
u2 methods_count 方法计数器 2
method_info methods 方法集合 n
u2 attributes_count 附加属性计数器 2
attribute_info attributes 附加属性集合 n

 

一个class字节码文件主要由以下10部分组成:

1、MaginNamber

2、Version

3、Constant_pool

4、Access_flag

5、This_class

6、Super_class

7、Interfaces

8、Fields

9、Methods

10、Attributes

三、二进制文件解读,如下图所示:

一、 java class 字节码概述以及Java字节码结构

1、MaginNamber 即魔数,是用来标志class文件的,位于每一个java class 文件的最前面4个字节,值固定为0xCAFEBABE不变。虚拟机加载文件时会先检查这4个字节,如果不是0xCAFEBABE,则虚拟机拒绝加载该文件,这样就可以防止加载非class文件而造成虚拟机奔溃。

2、Version 即版本号,字段由2个长度为2个字节的字段组成,分别是Major Version 和 Minor Version,代表当前class文件的主版本号和次版本号 。不同的虚拟机支持Java class 文件的版本范围是不同的,所以在加载class文件之前可以先看看该class文件是否为当前虚拟机支持范围之内的,避免加载不支持的class文件。(高版本兼容低版本,反转不支持)

3、Constant_pool 即常量池,是从class文件的第9个字节开始。首先是2个字节(第9、第10两个字节)的长度字段constant_pool_count,表名常量池包含了多少个常量。接下来是二进制信息描述[constant_pool_conut-1]个常量,里面放的是字面常量和符号引用。

  字面常量主要包含文本串以及被声明final的常量。

  符号引用包含类和接口的全局限定名、字段的名称和描述符、方法的名称和描述符。

4、Access_flag,主要保存当前类的访问权限。

5、This_cass,主要保存当前类的全局限定名在常量池的索引。

6、Super_class,主要保存当前类的父类的全局限定名在常量池里的索引。

7、Interfaces,主要保存当前类的接口列表,包含两部分内容:interfaces_count和interfaces[interfaces_count]

interfaces_count指的是当前类实现的接口数目。

interfaces[]是包含interfaces_count 个接口的全部限定名的索引的数组。

8、Fields,主要保存当前类的成员列表,包含两部分内容:fields_count 和 fields[fields_count ].

fields_count 是类变量和实例变量字段的数量总和。

field[]是包含字段详细信息列表。

9、Methods,主要保存当前类的方法列表,包含两部分内容:Methods_count 和 Methods[Methods_count].

Methods_count是该类或者接口显式定义的方法的数量。

Methods[]是包含方法信息的一个详细列表。

10、Attributes,主要保存当前类attribute列表,包含Attributes_count 和Attributes[Attributes_count].

好了,暂时就先学习到这吧,眼睛都看晕了