Java 诞生之时有句著名的宣传口号“Write Once, Run Anywhere.”。但是,Java 语言本身不具备跨平台的能力,而是 JVM 提供了跨平台的能力。

事实上,不仅 Java 可以运行在 JVM 上,现在已经出现了其他的语言可以运行在 JVM 上,如 Clojure、Scala 等。也就是说,JVM 并不和包括 Java 在内的任何语言绑定,只与“Class 文件”这种特定的二进制文件格式相关联,Class 文件包含了 Java 虚拟机指令集和符号表以及若干其他辅助信息。这篇文章就主要介绍存储字节码的 Class 文件。

任何一个 Class 文件都对应着唯一一个类或接口的定义信息,但是,类或接口的定义信息并非一定要在类文件中。

Class 文件是一组以 8 位为基础单位的字节流(二进制流),每个数据项严格按照顺序节凑排列在 Class 文件中,中间没有任何分隔符。多字节的数据项按照大端序存储(高字节存储在最低地址位)。

基本概念

JVM 规范规定,Class 文件采用一种类似于 C 语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数

  • 无符号数是基本的数据类型,以 u1、u2、u3、u4 分别代表 1 个字节、2 个字节、3 个字节、 4 个字节。无符号数可以用来描述数字、索引引用、数量值或者按照 UTF-8 编码构成字符串值。
  • 表由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯地以"_info"结尾。表用于描述有层次关系的复合结构的数据,这个 Class 文件本质上就是一张表。

文件结构

   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 文件就对应这样一个 ClassFile 的结构。

无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器加若干个连续的数据项的形式,这是称这一序列连续的某一个类型的数据为某一类型集合。如 fields_count 来描述 field_info 的数量(这些 field_info 就构成一个集合)。

ClassFile 中每个项目解释如下表(attributes_count 和 attributes[] 比较复杂,这里暂不介绍,我会在文章末尾提供参考资料):

item 含义
magic 魔数,它的唯一作用时确定这个文件能否为一个能被虚拟机接受的 Class 文件。许多文件标准中都使用魔数来进行身份标识。Class 文件的魔数值为:0xCAFEBABE
minor_version 这个类文件的次版本号。
major_version 这个类文件的主版本号。
constant_pool_count 常量池容器计数值,等于常量池(constant_pool) 中实体数量加 1 。常量池的索引只有在比零大,比该值小才认为是有效的。
constant_pool[] 常量池中的结构表示字符串常量、类名字、接口名字、字段(field name)、其他常量(指向 ClassFile 中的其他结构、子结构)。
access_flag 访问标志。用于识别一些类或接口层次的访问信息,包括:这个 Class 是类还是接口;是否定义为 public;是否定义为 abstract 类型;如果是类的话,是否被声明为 final 等。
this_class 用于确定这个类的全限定名。
super_class 用于确定这个类的父类的全限定名。
interfaces_count 用于标识类实现了几个接口。
interfaces[] 类实现了哪些接口,按 implements 后的顺序显示在这个集合中。
fields_count 用于描述接口或者类中声明的变量的数量,字段包括类级变量以及实例级变量
fields[] 用于描述接口或者类中声明的变量,字段包括类级变量以及实例级变量。描述信息包括:字段的作用域(public、private、protected)、实例变量还是类变量(static)、可变性(final)、并发可见性(volatile)、字段数据类型、字段名称、可否被序列化。除字段数据类型、字段名称需要引用常量池中常量来描述外,其余均用标志位来表示。
methods_count 接口或类中方法的数量。
methods[] 描述接口或类中的方法。

Class 的文件格式大体上就是这样,还有大量细节没有描述,如常量池中各种常量项的结构、访问标志具体值与名称、字段描述符、方法描述符、属性表等。由于这些都是规范,这里不再写了,想更近一步了解的话,可以阅读 Java 虚拟机规范。

参考:

The Java Virtual Machine Specification, Java SE 8 Edition

《深入理解Java虚拟机》

Java 类文件结构的更多相关文章

  1. 《深入理解java虚拟机》笔记——简析java类文件结构

    一直不太搞得明确jvm究竟是如何进行类载入的,在看资料的过程中迷迷糊糊.在理解类载入之前,首先看看java的类文件结构究竟是如何的,都包含了哪些内容. 最直接的參考当然是官方文档:The Java® ...

  2. 不知道Java类文件结构的同学,看这篇文章就够了

    一.前言 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步.经过多年的发展,目前的计算机仍然只能识别0和1,但是由于近10年内虚拟机以及大量建立在虚拟机之上的程 ...

  3. Java类文件结构详解

    概述: Class文件结构是了解虚拟机的重要基础之一,如果想深入的了解虚拟机,Class文件结构是不能不了解的.Class文件是一组以8位字节为基础单位的二进制流,各项数据项目严格按照顺序紧凑地排列在 ...

  4. java类文件结构笔记

    注:新的博客地址 - https://zhengw-tech.com/archives/ 我们都知道java实现跨平台靠的是虚拟机技术,将源文件编译成与操作系统无关的,只有虚拟机能识别并执行的字节码文 ...

  5. Java类文件结构

    一.概述 实现语言无关性的基础是虚拟机和字节码存储格式.Java虚拟机不和包括Java在内的任何语言绑定,只与"Class文件"这种特定的二进制文件所关联,Class文件中包含了J ...

  6. Java类文件结构及javac的ClassReader类解读

    首先来看一下ClassFile,类注释如下: A JVM class file. Generic Java classfiles have one additional attribute for c ...

  7. Java虚拟机,类文件结构深度解析

    Java类文件结构 Java虚拟机不和包括Java在内的任何语言绑定,只与 "Class文件" 这种特定的二进制文件所关联, Class文件中包含了Java虚拟机指令集合符号表以及 ...

  8. JVM学习笔记(三):类文件结构

    代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步. 实现语言无关性的基础是虚拟机和字节码存储格式.Java虚拟机不和包括Java在内的任何语言绑定,只与&quo ...

  9. JVM类文件结构

    作为一名Java后台开发的程序员, 深入理解JVM, 重要性不言而喻, 这篇文章主要是记录JVM类文件结构相关知识. 2. 实例 这部分比较抽象, 所以以实例的形式来学习. 这部分作为资料, 以便后面 ...

随机推荐

  1. 基础--Redis在Windows环境下的安装

    1. 安装Redis 1.1 下载安装包 https://github.com/ServiceStack/redis-windows#3-run-the-redis-serverexe-using-t ...

  2. scrapy回调函数传递参数

    scrapy.Request 的callback传参的两种方式 1.使用 lambda方式传递参数 def parse(self, response): for sel in response.xpa ...

  3. rpm软件包管理的详细解读

    CentOS系统上使用rpm命令管理程序包:安装.卸载.升级.查询.校验.数据库维护 1.基本安装 rpm -ivh PackageFile 2.rpm选项 rpm -ivh --test Packa ...

  4. 一些常用的api接口、

    taobao ip地址的api http://ip.taobao.com/service/getIpInfo.php?ip=IP 返回参数 code 状态码 data 数据信息 country 国家  ...

  5. HighCharts之2D堆面积图

    HighCharts之2D堆面积图 1.HighCharts之2D堆面积图源码 StackedArea.html: <!DOCTYPE html> <html> <hea ...

  6. 百度地图JavaScript API本地搜索的结果面板

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  7. Linux查询一台机器的IP地址和其对应的域名

    Linux查询一台机器的IP地址和其对应的域名 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ nslookup > 127.0.0.1 Server: ...

  8. PageBase 公共基础类

    PageBase 公共基础类 using System; using System.Collections.Generic; using System.Linq; using System.Web; ...

  9. Centos运行Mysql因为内存不足进程被杀

    今天刚刚申请了一个新的域名,在申请完域名刚准备绑定给小伙伴分享注册新域名的喜悦时,刚把网站发到我们小伙伴们的讨论群里,却发现访问不了了,提示,数据库连接失败! 真的时一个尴尬.....    所有人都 ...

  10. 举例MyBatis的常用的API及方法

    在使用MyBatis框架是,主要涉及以下几个API: 1.SqlSessionFactoryBuilder该对象根据MyBatis配置文件SqlMapConfig.xml构建SQLSessionFac ...