深入理解Java虚拟机--类文件结构

简介: 本内容介绍了Java虚拟机与Class文件的关系及其内部结构。Class文件是一种与语言无关的二进制格式,包含JVM指令集、符号表等信息。无论使用何种语言,只要能生成符合规范的Class文件,即可在JVM上运行。文章详细解析了Class文件的组成,包括魔数、版本号、常量池、访问标志、类索引、字段表、方法表和属性表等,并说明其在Java编译与运行过程中的作用。

Java虚拟机不和包括Java在内的任何语言绑定,它只与“Class文件”这种特定的二进制文件格式所关联,Class文件中包含了Java虚拟机指令集和符号表以及若干其他辅助信息。任一门功能性语言都可以表示为一个能被Java虚拟机所接受的有效的Class文件,所以虚拟机并不关系Class的来源是何种语言

2.Class类文件的结构

任何一个Class文件都对应着唯一一个类或接口的定义信息,但反过来说,类或接口并不一定得定义在文件里(譬如类或接口也可可以通过类加载器直接生成)。

  • Class文件说一组以8位字节为基础单位的二进制流,各个数据项目严格的按照顺序紧凑地排列在Class文件中,中间没有任何分隔符,所以Class文件中存储的内容几乎都是程序运行的必要数据,没有空隙存在
  • 当遇到需要占用8位字节以上空间的数据项时,则会按照高位在前的放松分割成若干个8位字节进行存储
  • Class文件格式采用一种类似于V语言结构体的伪结构体存储数据,伪结构中只有两周数据类型:无符号数、表
  • 无符号数属于基本数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节、8个字节的无符号数,无符号数可以用来描述数字,索引引用、数量值、按照UTF-8bianma构成字符串值
  • 表说由多个无符号数,或其他表作为数据项构成的复合数据类型,所有表都习惯性地以“  _info”结尾
  • 整个Class文件本质上将是一张表
  • 由于Class文件没有设置任何间隔,所以一切数据项都有严格的规定 ##2.1 魔数与Class文件的版本
  • Class文件前4个字节为魔数,唯一的作用的是确定这个文件能被虚拟机接受。魔数固定值为0xCAFEBABE为咖啡的寓意
  • 魔数后的4个字节,分别为此版本号与主版本号,版本号必须是虚拟机可执行版本内,该Class文件才可被虚拟机执行

2.2常量池

主版本号之后啥常量池入口,常量池可以理解为Class文件之中的资源仓库,它是Class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一,同时它还是Class文件中第一个出现的表类型数据项目

  • 常量池的常量数量不固定,所以常量池需要放置一个u2类型的数据,代表常量池容量计数值(从1开始,如果是22,则代表有21项常量) 常量池主要存放两大类常量:
  • 字面量:比较接近于java语言层面的常量概念,如文本字符串、声明为final的常量值等
  • 符号引用:属于编译器原理方面的概念,包括三类常量:类和接口的全限定名、字段的名称和描述符、方法的名称和描述符 Java代码在进行Javac编译的时候,不像C和C++那样有“连接”这一步骤,而是在虚拟机加载Class文件的时候进行动态链接。也就算说Class文件中不会保存各个方法、字段的最终内存布局,因此这些字段、方法的符号引用不用经过运行期转换的话无法得到真正的内存地址,也就无法直接被虚拟机使用。当虚拟机运行时,,需要从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址之中。

2.3访问标志

常量池之后,紧接着的两个字节代表访问标志,这个标志用于一些类或者接口层次的访问信息,包括:这个Class是类还是接口;是否定义为public类型;是否定义abstract类型;如果是类的话,是否被声明为final等。

2.4类索引、父类索引、与接口索引集合

类索引、父类索引都是一个u2类型的数据,而接口索引集合是一组u2类型的数据的集合,Class文件中由这三项数据来确定这个类的继承关系。类索引用于确定这个类全限定名,父类索引用于确定这个类的父类的全限定名。由于所有Java类最多只有一个父类,所以父类索引只有一个。接口索引集,描述这个类实现了哪些接口,这些被实现的接口将按implements语句后的接口顺序从左到右排序在接口索引集合中。

2.5字段表集合

(filed_info)字段表描述接口或者类中声明的变量。

  • 字段(field)包括类级变量以及实例级变量,但不包括方法内部声明的局部变量。
  • 描述的内容可以包括字段的作用域(public、private..)、是实例变量还是类变量(static修饰符)、可变形(final)等等

2.6方法表集合

  • Class文件存储格式中对方法对描述与对字段的描述一致
  • 方法里的Java代码,经过编译器编译成字节码指令后,存放在方法熟悉表集合中一个名为“Code”的属性里面。

2.6属性表集合

在Class文件、字段表、方法表都可以携带自己的属性表集合,以描述某些场景专有的信息


转载来源:https://juejin.cn/post/7001658503538409503

相关文章
|
4月前
|
存储 Java 索引
用Java语言实现一个自定义的ArrayList类
自定义MyArrayList类模拟Java ArrayList核心功能,支持泛型、动态扩容(1.5倍)、增删改查及越界检查,底层用Object数组实现,适合学习动态数组原理。
189 4
|
4月前
|
IDE JavaScript Java
在Java 11中,如何处理被弃用的类或接口?
在Java 11中,如何处理被弃用的类或接口?
269 5
|
4月前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
350 5
|
4月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
256 1
|
4月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
230 1
|
4月前
|
Java Go 开发工具
【Java】(8)正则表达式的使用与常用类分享
正则表达式定义了字符串的模式。正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
318 1
|
4月前
|
存储 Java 程序员
【Java】(6)全方面带你了解Java里的日期与时间内容,介绍 Calendar、GregorianCalendar、Date类
java.util 包提供了 Date 类来封装当前的日期和时间。Date 类提供两个构造函数来实例化 Date 对象。第一个构造函数使用当前日期和时间来初始化对象。Date( )第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
244 1
|
4月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
269 1
|
9月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
842 55
|
4月前
|
存储 缓存 Java
我们来说一说 JVM 的内存模型
我是小假 期待与你的下一次相遇 ~
381 5