java虚拟机-字节码文件结构

本文深入探讨Java语言与Java虚拟机(JVM)之间的关系,揭示JVM如何成为跨平台和跨语言的运行环境。详细解析Class文件结构,包括魔数、版本号、常量池、访问标志等关键组成部分,以及它们在JVM中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.java语言与java虚拟机的关系

得益于虚拟机,java被称为跨平台的语言。

同时,java虚拟机也可以被看作是跨语言的平台。java虚拟机不与任何语言(包括java)绑定,它只与Class文件 这种特定的二进制文件强关联。任何语言,只要能编译成符合特定规则的Class文件,就都可以在java虚拟机上运行。如下图1 所示:

图1  java虚拟机与语言的关系

2.Class文件结构

任何一个Class文件都对应着一个类或一个接口的定义信息。但是反过来,类或接口不一定都得定义在文件里,因为还可以动态生成,直接送入类加载器中。

Class文件是一组以8个字节为单位的二进制流,按严格顺序排列,没有任何分隔符。

Class文件采用 “无符号数” 和 “表” 来记录数据。

2.1 无符号数

其中,无符号数是基本的数据类型,u1,u2,u4,u8来分别代表1,2,4,8个字节的无符号数。无符号数可以描述数字,索引引用,数量值或者以UTF-8编码的字符串值。

2.2 表 

表是由多个无符号数或者其他表作为数据项构成的数据结构。以_info结尾。整个Class文件本身可视为一张表。

2.3.Class文件记录结构

2.3.1 魔数(magic number)

Class文件的前4个字节是固定的,值为cafebabe.是该字节码文件是否可以被虚拟机接受的标识。

紧接着魔数后的四个字节是java的版本号。《Java虚拟机规范》中明确规定:即使字节码文件结构没有任何改变,也不允许虚拟机执行超过其版本号的Class文件。

2.3.2 常量池

常量池中保存了两大类常量:字面量和符号引用

字面量如:字符串,被声明为final的常量值登录。

符号引用:类和接口的全限定名,字段/方法的名称和描述符、方法句柄和方法类型、动态调用点和动态常量等。

java代码在用javac编译时,没有连接这一步(c/c++有),而是在虚拟机加载Class文件时进行动态连接,即 java中的各个方法、字段等最终在内存中的地址在Class文件中不会有的,当虚拟机做类加载时,会从常量池中获得对应的符号引用,经过在类创建或运行时解析、翻译到具体的内存地址当中。用命令 javap -verbose XX(字节码名称)  可以输出某个字节码中的常量表

2.3.3 访问标志

访问标志用于识别一些类或接口层次的访问信息,如这个Class是类还是接口,是private还是public的等

2.3.4 类索引、父类索引和接口索引集合

该数据是个u2类型的数据集合,Class文件中通过这3项来确定该类型的继续关系。

注:父类索引只有一个,因为java没有多重继续,除了java.lang.Object外,其他所有的类都有父类。

2.3.5 字段表集合

字段表(field_info)描述接口或类中声明的变量。包括类变量或实例变量(不包括方法内部声明的局部变量,局部变量保存在栈中的局部变量表中)。field_info结构图如下,除过图里的,字段表还有 acc_volatile标志(volatile标志),acc_transient标志(transient关键字修饰)

2.3.6 方法表集合

 该部分为字段表与方法表的共同部分,除此之外,方法表没有acc_volatile,acc_transient标志,但多了acc_synchronized,acc_native,acc_strictfp和acc_abstract标识。方法里吗的代码存放到字节码文件的Code属性里,Code是方法属性表集合中一个最具扩展性的项目。

方法表集合与上述字段表集合结构类似:

2.3.7 属性表集合

属性表在Class文件、字段表、方法表等都可以有自己的属性表。 属性表与其他结构不同,不再需要遵循严格的属性,只要不与已有属性重名。下图为属性表集合里的code属性。

在Class文件里,Code属性用于描述代码,所有其他的项目都用于描述元数据。

 总结:对一个完整的类,看一下字节码结构:

源码:

public class Solution{
    public int temp=0;
    public  final long test=1;

    public  void fun1(){
         Integer nouse=0;
        System.out.println("test:"+test);
    }
    public static void main(String[] args){

        int[] arr={6,1,5,3,2,4};

        int[] res=SelectSortArray.selectSort(arr);
        for(int i:res){
            System.out.println(i);
        }
    }
}

通过javap得出的字节码结构:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值