Java 类文件结构
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 类文件结构的更多相关文章
- 《深入理解java虚拟机》笔记——简析java类文件结构
一直不太搞得明确jvm究竟是如何进行类载入的,在看资料的过程中迷迷糊糊.在理解类载入之前,首先看看java的类文件结构究竟是如何的,都包含了哪些内容. 最直接的參考当然是官方文档:The Java® ...
- 不知道Java类文件结构的同学,看这篇文章就够了
一.前言 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步.经过多年的发展,目前的计算机仍然只能识别0和1,但是由于近10年内虚拟机以及大量建立在虚拟机之上的程 ...
- Java类文件结构详解
概述: Class文件结构是了解虚拟机的重要基础之一,如果想深入的了解虚拟机,Class文件结构是不能不了解的.Class文件是一组以8位字节为基础单位的二进制流,各项数据项目严格按照顺序紧凑地排列在 ...
- java类文件结构笔记
注:新的博客地址 - https://zhengw-tech.com/archives/ 我们都知道java实现跨平台靠的是虚拟机技术,将源文件编译成与操作系统无关的,只有虚拟机能识别并执行的字节码文 ...
- Java类文件结构
一.概述 实现语言无关性的基础是虚拟机和字节码存储格式.Java虚拟机不和包括Java在内的任何语言绑定,只与"Class文件"这种特定的二进制文件所关联,Class文件中包含了J ...
- Java类文件结构及javac的ClassReader类解读
首先来看一下ClassFile,类注释如下: A JVM class file. Generic Java classfiles have one additional attribute for c ...
- Java虚拟机,类文件结构深度解析
Java类文件结构 Java虚拟机不和包括Java在内的任何语言绑定,只与 "Class文件" 这种特定的二进制文件所关联, Class文件中包含了Java虚拟机指令集合符号表以及 ...
- JVM学习笔记(三):类文件结构
代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步. 实现语言无关性的基础是虚拟机和字节码存储格式.Java虚拟机不和包括Java在内的任何语言绑定,只与&quo ...
- JVM类文件结构
作为一名Java后台开发的程序员, 深入理解JVM, 重要性不言而喻, 这篇文章主要是记录JVM类文件结构相关知识. 2. 实例 这部分比较抽象, 所以以实例的形式来学习. 这部分作为资料, 以便后面 ...
随机推荐
- ios开发之自定义textView
自定义textView,从理论上讲很简单,根据需求自定义,比如我在开发中的需求就是现实一个字数的限制以及根据输入的文字改变提示剩余字数,那么开始我的基本思路就是自定义一个View,而里面包含一个子控件 ...
- python替换脚本
任何场合都用的到的全文替换 #!/usr/bin/python import sys if len(sys.argv) < 5: print 'usage: python %s from to ...
- Android项目中的换肤总结
纵观现在各种Android app,其换肤需求可以归为 白天/黑夜主题切换(或者别的名字,通常2套),如同花顺/自选股/天天动听等,UI表现为一个switcher. 多种主题切换,通常为会员特权,如Q ...
- R语言︱数据规范化、归一化
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 笔者寄语:规范化主要是因为数据受着单位的影响较 ...
- PHP常见错误
1.关于单引号和双引号的区别. $sql="insert into tableName values ('".$name."','".$email." ...
- R语言︱文本(字符串)处理与正则表达式
处理文本是每一种计算机语言都应该具备的功能,但不是每一种语言都侧重于处理文本.R语言是统计的语言,处理文本不是它的强项,perl语言这方面的功能比R不知要强多少倍.幸运的是R语言的可扩展能力很强,DN ...
- Caused by: Unable to locate parent package [json-default] for [class com.you.user.action.StudentActi
1.错误描述 信息: Choosing bean (struts) for (com.opensymphony.xwork2.util.TextParser) 2014-7-13 1:52:04 or ...
- Regex 正则替换指定范围全部字符串
1.正则替换字符-------------------------------------------------------------------------------------------- ...
- FFMPEG 在ubuntu下的安装与使用
转载自 http://www.cnblogs.com/dwdxdy/p/3240167.html (部分一:安装) ffmpeg的安装: 1.下载源文件(以ffmpeg1.2.1为例): http:/ ...
- php composer的学习之路(一)
composer的介绍请看这里 http://docs.phpcomposer.com/00-intro.html composer的安装过程我就不介绍了,windows系统下跟其他安装没区别,一直 ...