JVM的基本原理和class文件结构(浅谈)

前言:

本篇主要讲解了JVM对class的文件结构的一个读取翻译过程,对class的文件结构的魔数、版本号、常量池计数器、常量池、常量池表、接口计数器、接口集合(表结构)、字段计数器、字段(表结构)、方法计数器、方法(表结构)、属性计数器、属性(表信息)的结构化分析。

1、jvm基础

  • jvm的编码过程

jvm是一种规范,所有可以编译成class的文件都可以执行;jvm和java无关,所有可以编译成class的语言都可以在jvm运行。

  • jvm的实现

jvm官方默认实现方式hotSpot java -version

  • JDK JRE JVM

JDK=JRE(java运行时环境)+开发工具

JRE=jvm(虚拟机)+core lib(核心类库)

JVM java虚拟机

2、class文件的分析

官方文档位置:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.1

  • 二进制字节码的结构

ClassFile {

u4 magic;

u2 minor_version;

u2 major_version;

u2 constant_pool_count;

cp_info constant_pool[constant_pool_count-1];

u2 access_flags;

u2 this_class;

u2 super_class;

u2 interfaces_count;

u2 interfaces[interfaces_count];

u2 fields_count;

field_info fields[fields_count];

u2 methods_count;

method_info methods[methods_count];

u2 attributes_count;

attribute_info attributes[attributes_count];

}

  • class文件读取的是二进制文件流,对应的class十六进制文件查看

  • class文件十六进制的内容解析

  • class文件的反汇编

java源码

packagecom.java.czing.jvm.classfile;

/** * @Description TODO

* @Author wangchengzhi * @Date 2023/2/17 15:36 */

publicclassClassTest {

publicClassTest() {

}

}

  • 常量池(存放所有常量)

  1. class文件主要结构梳理

  • 魔数(4字节):Class文件的标志

前几位固定数值为CA FE BA BE标志该文件为class文件;

它的唯一作用是确定这个文件是否为一个能被虚拟机接受的有效合法的Class文件

  • Class文件版本号

紧挨着魔数的4字节是次版本号Minor Version和主版本号Major Version

(class文件的版本号例如:JDK1.7默认为51.0JDK1.8默认为52.0)

  • 常量池计数器:constant_pool_count

由于常量池的数量不固定,时长时短,所以需要放置两个字节来表示常量池容量计数值

常量池容量计数值(u2类型):从1开始,表示常量池有多少项常量。即constant_pool_count=1表示常量池中有0个常量项。例如:常量池的数量 00 10(16进制) = 1*161+0*160=16,数量16-1=15。

  • 常量池:constant_pool

常量池中每一项常量都是一个表

u1:一个字节。

u2:两个字节。

  • 访问标志:access_flag

在常量池后,紧跟着访问标记。该标记使用两个字节表示,用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口;是否定义为public类型;是否定义为abstract类型;如果是类的话,是否被声明为final等。各种访问标记如下所示:

标志名称

标志值

含义

ACC_PUBLIC

0x0001

标志位public类型

ACC_FINAL

0x0010

标志被声明为final,只有类可以设置

ACC_SUPER

0x0020

标志允许使用invokespecial字节码指令的新语义,JDK1.0.2之后编译出来的类的这个标志默认为真。(使用增强的方法调用父类方法)

ACC_INTERFACE

0x0200

标志这是一个接口

ACC_ABSTRACT

0x0400

是否为abstract类型,对于接口或者抽象类来说,次标志值为真,其他类型为假

ACC_SYNTHETIC

0x1000

标志此类并非由用户代码产生(即:由编译器产生的类,没有源码对应)

ACC_ANNOTATION

0x2000

标志这是一个注解

  • 类索引(this_class)、父类索引(super_class)、接口计数器(INTERFACE_COUNT)、接口索引集合(interfaces),均为两字节

在访问标记后,会指定该类的类别、父类类别以及实现的接口

  • 字段表集合

Fields:

1.用于描述接口或类中声明的变量。字段(field)包括类级变量以及实例级变量,但是不包括方法内部、代码块内部声明的局部变量。

2.字段叫什么名字、字段被定义为什么数据类型,这些都是无法固定的,只能引用常量池中的常量来描述。

3.它指向常量池索引集合,它描述了每个字段的完整信息。比如字段的标识符、访问修饰符(public、private或protected)、是类变量还是实例变量(static修饰符)、是否是常量(final修饰符)等

fields_count(字段计数器):

1.fields_count的值表示当前class文件fields表的成员个数。使用两个字节来表示。

2.fields表中每个成员都是一个field_info结构,用于表示该类或接口所声明的所有类字段或者实例字段,不包括方法内部声明的变量,也不包括从父类或父接口继承的那些字段。

fields[](字段表):

1.fields表中的每个成员都必须是一个fields_info结构的数据项,用于表示当前类或接口中某个字段的完整描述。

2.一个字段的信息包括如下这些信息。这些信息中,各个修饰符都是布尔值,要么有,要么没有。

(1)作用域(public、private、protected)

(2)是实例变量还是类变量(static修饰符)

(3)可变性(final)

(4)并发可见性(volatile修饰符,是否强制从主内存读写)

(5)可否序列化(transient修饰符)

(6)字段数据类型(基本数据类型、对象、数组)

(7)字段名称

字段表结构:

类型

名称

含义

数量

U2

access_flags

访问标志

1

U2

name_index

字段名索引

1

U2

descriptor_index

描述符索引

1

U2

attributes_count

属性计数器

1

attribute_info

attributes

属性集合

attributes_count

  • 方法计数器(methods_count)

methods_count的值表示当前class文件methods表的成员个数。使用两个字节来表示。

  • 方法表(methods)

1.methods表中的每个成员都必须是一个method_info结构,用于表示当前类或接口中某个方法的完整描述。如果某个method_info结构的access_flags项既没有设置ACC_NATIVE标志也没有设置ACC_ABSTRACT标志,那么该结构中也应包含实现这个方法所用的Java虚拟机指令。

2.method_info结构可以表示类和接口中定义的所有方法,包括实例方法、类方法、实例初始化方法和类或接口初始化方法

3、方法表的结构同字段表

  • 属性计数器(attributes_count - u2)

attributes_count的值表示当前class文件属性表的成员个数。属性表中每一项都是一个attribute_info结构。

  • 属性表(attributes)

属性表的每个项的值必须是attribute_info结构。属性表的结构比较灵活,各种不同的属性只要满足以下结构即可。

类型

名称

数量

含义

U2

attribute_name_index

1

属性名索引

U4

attribute_length

1

属性长度

U1

info

attribute_length

属性表

附件:JVM的官方文档参考https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.10.1.7

结语:

jvm的class文件结构化梳理,欢迎留言交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值