概述
在Java语言中,Java虚拟机只能理解字节码
(class文件
),它不面向任何处理器,不与任何语言绑定,只与Class文件
这种特定的二进制文件格式所关联。
Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。
另一方面由于JVM虚拟机
不与任何语言、机器绑定,因而任何语言的实现着都可以将Java虚拟机作为语言的运行基础,以Class文件作为他们的交付媒介。例如Clojure
(Lisp 语言的一种方言)、Groovy
、JRuby
等语言都是运行在 Java 虚拟机之上。
下图展示了不同的语言被不同的编译器编译成.class
文件最终运行在 Java 虚拟机之上的过程:
Class文件的结构
根据《Java虚拟机规范》,Class 文件通过 ClassFile
定义,而且文件结构采用一种类似c语言结构体的伪结构体。这种伪结构体只有两种两种数据类型:“无符号数”和“表”。
- 无符号数:属于基本的数据结构,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节、8个字节的无符号数。无符号数可以用来描述数字、索引引用、数字量值或者按照UTF-8编码构成字符串值
- 表:由多个无符号数或者其他表作为数据项构成的复合数据结构,为了便于区分,所有表的命名都习惯以 “_info” 结尾。
在正式开始讲,我们需要说明一点,Class文件的结构不像XML那样的结构化描述语言,它以8个字节为基础单位,各个数据项目严格按照顺序紧凑地排列在文件中,中间没有添加任何分隔符号,因而在Class的数据项无论是顺序还是数量,甚至数据存储的字节序(大端存储,Big-Endian)这样的细节,都是被严格限定的,哪个字节代表什么含义,长度是多少,先后顺序如何,全部都不允许改变。
ClassFile
的结构如下:
ClassFile {
u4 magic; //Class 文件的标志
u2 minor_version;//Class 的小版本号
u2 major_version;//Class 的大版本号
u2 constant_pool_count;//常量池的数量
cp_info constant_pool[constant_pool_count-1];//常量池
u2 access_flags;//Class 的访问标记
u2 this_class;//当前类
u2 super_class;//父类
u2 interfaces_count;//接口
u2 interfaces[interfaces_count];//一个类可以实现多个接口
u2 fields_count;//Class 文件的字段属性
field_info fields[fields_count];//一个类会可以有多个字段
u2 methods_count;//Class 文件的方法数量
method_info methods[methods_count];//一个类可以有个多个方法
u2 attributes_count;//此类的属性表中的属性数
attribute_info attributes[attributes_count];//属性表集合
}
通过对ClassFile
的分析,我们便可以知道class文件的组成。
上边的一些属性什么的,描述都很抽象,因而这里以一段典型的java代码产生的class文件为基础结合进行讲解。
一段典型的Java程序代码如下:
package com.test;
//接口类
interface Car {
void drive();
}
//实现类
public class BMWCar implements Car{
private String name;
public BMWCar() {
name = "宝马";
}
@Override
public void drive() {
System.out.println("BMW car drive." + name);
}
}
通过javac
命令对代码进行编译,生成的class文件内容如下:
Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000: CA FE BA BE 00 00 00 3B 00 33 07 00 02 01 00 0F J~:>...;.3......
00000010: 63 6F 6D 2F 74 65 73 74 2F 42 4D 57 43 61 72 07 com/test/BMWCar.
00000020: 00 04 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F .....java/lang/O
00000030: 62 6A 65 63 74 07 00 06 01 00 0C 63 6F 6D 2F 74 bject......com/t
00000040: 65 73 74 2F 43 61 72 01 00 04 6E 61 6D 65 01 00 est/Car...name..
00000050: 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 .Ljava/lang/Stri
00000060: 6E 67 3B 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 ng;...<init>...(
00000070: 29 56 01 00 04 43 6F 64 65 0A 00 03 00 0D 0C 00 )V...Code.......
00000080: 09 00 0A 08 00 0F 01 00 06 E5 AE 9D E9 A9 AC 09 .........e..i),.
00000090: 00 01 00 11 0C 00 07 00 08 01 00 0F 4C 69 6E 65 ............Line
000000a0: 4E 75 6D 62 65 72 54 61 62 6C 65 01 00 12 4C 6F NumberTable...Lo
000000b0: 63 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 calVariableTable
000000c0: 01 00 04 74 68 69 73 01 00 11 4C 63 6F 6D 2F 74 ...this...Lcom/t
000000d0: 65 73 74 2F 42 4D 57 43 61 72 3B 01 00 05 64 72 est/BMWCar;...dr
000000e0: 69 76 65 09 00 18 00 1A 07 00 19 01 00 10 6A 61 ive...........ja
000000f0: 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D 0C 00 va/lang/System..
00000100: 1B 00 1C 01 00 03 6F 75 74 01 00 15 4C 6A 61 76 ......out...Ljav
00000110: 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D a/io/PrintStream
00000120: 3B 07 00 1E 01 00 17 6A 61 76 61 2F 6C 61 6E 67 ;......java/lang
00000130: 2F 53 74 72 69 6E 67 42 75 69 6C 64 65 72 08 00 /StringBuilder..
00000140: 20 01 00 0E 42 4D 57 20 63 61 72 20 64 72 69 76 ....BMW.car.driv
00000150: 65 2E 0A 00 1D 00 22 0C 00 09 00 23 01 00 15 28 e....."....#...(
00000160: 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E Ljava/lang/Strin
00000170: 67 3B 29 56 0A 00 1D 00 25 0C 00 26 00 27 01 00 g;)V....%..&.'..
00000180: 06 61 70 70 65 6E 64 01 00 2D 28 4C 6A 61 76 61 .append..-(Ljava
00000190: 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 4C 6A /lang/String;)Lj
000001a0: 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 42 ava/lang/StringB
000001b0: 75 69 6C 64 65 72 3B 0A 00 1D 00 29 0C 00 2A 00 uilder;....)..*.
000001c0: 2B 01 00 08 74 6F 53 74 72 69 6E 67 01 00 14 28 +...toString...(
000001d0: 29 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 )Ljava/lang/Stri
000001e0: 6E 67 3B 0A 00 2D 00 2F 07 00 2E 01 00 13 6A 61 ng;..-./......ja
000001f0: 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 va/io/PrintStrea
00000200: 6D 0C 00 30 00 23 01 00 07 70 72 69 6E 74 6C 6E m..0.#...println
00000210: 01 00 0A 53 6F 75 72 63 65 46 69 6C 65 01 00 0B ...SourceFile...
00000220: 42 4D 57 43 61 72 2E 6A 61 76 61 00 21 00 01 00 BMWCar.java.!...
00000230: 03 00 01 00 05 00 01 00 02 00 07 00 08 00 00 00 ................
00000240: 02 00 01 00 09 00 0A 00 01 00 0B 00 00 00 3D 00 ..............=.
00000250: 02 00 01 00 00 00 0B 2A B7 00 0C 2A 12 0E B5 00 .......*7..*..5.
00000260: 10 B1 00 00 00 02 00 12 00 00 00 0E 00 03 00 00 .1..............
00000270: 00 0D 00 04 00 0E 00 0A 00 0F 00 13 00 00 00 0C ................
00000280: 00 01 00 00 00 0B 00 14 00 15 00 00 00 01 00 16 ................
00000290: 00 0A 00 01 00 0B 00 00 00 48 00 04 00 01 00 00 .........H......
000002a0: 00 1A B2 00 17 BB 00 1D 59 12 1F B7 00 21 2A B4 ..2..;..Y..7.!*4
000002b0: 00 10