Java 虚拟机能够识别的是.class文件,而不管上层使用的是何种语言编写的代码,只要编译器能够编译成符合Java 虚拟机规范的.class 文件,JVM就可以对该文件加载运行。
Java虚拟机提供的语言无关性。Sun 公司最成功的产品不是Java,而是Java虚拟机,实现了跨平台运行的基石:一次编写,到处运行。
Class类文件的结构
Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。当遇到需要占用8个字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8个字节进行存储。
下面就是通过命令
javac TestClass.java 以及 xxd TestClass.class TestClass.txt 命令将class 文件的字节码生成16进制的格式表现出来的。
这里我们先来弄清楚两个概念:无符号数、表
-
无符号数:基本数据类型,以u1、u2、u4、u8 来分别代表1个字节、2个字节、4个字节、8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成的字符串值。 cafe babe 0000 003d 0016 0a00 0200 0307 以这段字节为例 | 无符号数类型 | 字节数 |示例 | --- | --- |--- | | u1 | 1个字节 | ca| | u2 | 2个字节 | feba| | u4 | 4个字节 | be 0000 00| | u8 | 8个字节 | 3d 0016 0a00 0200 03|
-
表:多个无符号数或者其他表作为数据项构成的复合数据类型,所有的表名称后都加上了“_info”结尾。
| 类型 | 名称 | 数量 | 描述 |
|---|---|---|---|
| u4 | magic | 1 | class 文件的识别标志 |
| u2 | minor_version | 1 | jdk的次版本号 |
| u2 | major_version | 1 | jdk的主版本号 |
| u2 | constant_pool_count | 1 | 常量池中的常量个数(编号从1开始,21=22-1 个) |
| cp_info | constant_pool | constant_pool_count-1 | 常量池中的常量表 |
| u2 | access_flags | 1 | 访问标志 |
| u2 | this_class | 1 | 当前类 |
| u2 | super_class | 1 | 父类 |
| u2 | interface_count | 1 | 接口数量 |
| u2 | interfaces | interface_count | 接口引用索引 |
| u2 | fields_count | 1 | 字段数量 |
| field_info | fields | fields_count | 字段表 |
| u2 | method_count | 1 | 方法数量 |
| method_info | method | method_count | 方法表 |
| u2 | attributes_count | 1 | 属性个数 |
| attribute_info | attributes | attributes_count | 属性表 |
无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器+若干个连续的数据项的形式------> “集合”
接下来,我们分析一下我们自己编写的代码 生成的每个字节码所代表的含义。
public class TestClass {
private int m;
public int inc() {
return m + 1;
}
}
通过javac TestClass.java 以及 xxd TestClass.class TestClass.txt 生成的字节码文件,然后我整理成了excel 文件。
上图中最主要的部分就是常量池部分,该份文件中所指的常量池有21项,常量池的索引从1开始的,所以22-1=21 项。和工具jclasslib 生成的一样
然后,我分析了一部分除常量池的一些其他属性,见图
后面没分析,太费时间了,只要对应着《深入理解Java 虚拟机》第六章中的描述,静下心来一步步分析,可以得出这张excel 中的所有字节都是能找到对应的描述关系的。这里我推荐几个参考资料的路径:
-
ASCII对照表:tool.oschina.net/commons?typ…
-
JVM操作码规范:docs.oracle.com/javase/spec…
-
《深入理解Java 虚拟机》第六章
-《深入理解Java 虚拟机》第六章附录C 虚拟机字节码指令表
最后我附上一份我的分析草稿吧:
分析这玩意太费时了,本来想着在excel 中在做一次分析的,后来做着做着觉得这玩意单单靠自己看是不行的,一定要自己至少分一一遍,分析的时候,代码尽量写的简短,能够分析即可,不然,会让你分析到头大。分析了这个字节码文件,会对理解JVM有很大的帮助。对后面章节的学习很重要。