字节码
java程序通过javac命令编译,可以得到一个class文件,文件中是二进制信息,这个文件是字节码文件。JVM通过执行字节码文件来运行java程序。
既然字节码文件是由java程序编译而来,那么其中必然包含了java程序的所有信息,包括程序中的类名称、父类名称、方法名称、属性名称、常量等等。
字节码文件中的内容可以划分成以下几块区域,这些区域的位置是固定的。
我们写一个非常简单的类:
public class T0100_ByteCode01 {
}
其编译成字节码文件,通过sublime或者notepad++打开后,格式使用十六进制查看,是以下样子
cafe babe是所有字节码文件的开头,通过cafe babe就可以知道这个文件是字节码文件。cafe babe在字节码内容中又叫做Magic Number。
Magic Number后面的内容依次是:Minor Version、Major Version、constant_pool_count、constant_pool、access_flags、this_class、super_class、interfaces_count、interfaces、fields_count、fields、methods_count、methods、attributes_count-u2、attributes。
这些内容在字节码文件中的出现顺序一直是这样的,除非某些内容没有,那么其在字节码中是不会存在的。
以下是字节码内容的详细说明:
上表中的类型列中,u表示无符号,u后面的数字表示占多少个字节。像cp_info、field_info、method_info和attribute_info是无法确定其会占用多少空间的,因为每个java文件的这部分内容是不一样的。例如constant_pool常量池,每个java文件的常量池大小肯定不一样,所以无法用固定的字节长度。
常量池中的内容是十分复杂的,可以包含以下几个方面:
cp_info表:
表名列中的内容其实就是常量池中的内容可以划分出的几大类。但是在字节码文件中,大家都是二进制表示,而且排在一起,为了可以区分开来,所以有了标识位。不过,如果我们通过16进制的字节码文件去观察,实在是太费劲,java提供了一个命令javap对字节码文件进行了友好的翻译,方便我们查看。通过javap -v 字节码文件名,可以展示字节码文件的内容。
上图显示了javap命令展示的字节码文件信息。
我们看Constant pool部分的内容。第一行中,#1代表Constant pool中第一部分独立的内容;Methodref表示某个方法的应用(可以在cp_info表中查看Methodref的语义),那具体引用的是什么方法呢?我们看后面跟着#3和#13,表示要在Constant pool中查找#3和#13的信息。
#3在第三行,后面跟了个Class,表示是类信息,在看后面跟着#15,于是我们再看Constant pool中#15部分的信息。#15在最后一行,Utf8表示后面的内容单纯是个字符串,而且是java/lang/Object,此时,我们知道Methodref引用的是Object类的某个方法。具体是哪个方法,我们再看#13部分的信息。
#13后面是NameAndType,表示方法的名称和方法的入参与出参类型,其后面跟着#4和#5,在Constant pool中查找可以发现,#4表示init,#5表示()V。init表示构造方法,()V分成两部分看,前面的()表示方法没有入参,V表示方法的出参类型是void。到此时,我们知道了,Methodref引用的是Object中的无参构造方法。
Constant pool中的其他信息的查看方式也是一样的。
在字节码文件中,还有一部分内容非常重要,是methods,其中有个Code具体展示了某个方法的每行代码代表的字节码指令。
我们写的代码十分简单
public class T0100_ByteCode01 {
}
代码就是一个空类,但是其实默认是有一个无参构造方法的。所以在编译成字节码文件后,有三个指令需要执行。
第一个是aload_0,这个在字节码指令集中的意思是去加载Constant pool中0号槽的对象,Constant pool的0号槽默认就是这个类对象自身。也就是说,aload_0表示将this压入操作数栈的栈顶;invokespecial表示执行某个方法,后面跟着#1需要去Constant pool中查找语义,我们知道是指Object类中的无参构造方法,所以invokespecial #1表示执行此方法。最后return表示退出。
以上只是对字节码文件的一个粗略的描述,但是我们也对字节码文件的内容有了大致的印象。字节码文件是由java文件编译而来,所以必然包含了java文件中的所有信息。而且,字节码文件对这些信息进行了分类,以方便存储。