简书 许乐
转载请注明原创出处,谢谢!
1.最简单类的字节码文件
下面我们来一个简单的类,并编译成class文件。
public class Test {
}
在JDK的bin目录中,Oracle公司已经为我们准备好了一个专门用于分析Class文件字节码的工具: javap
xule05deMacBook-Pro:boke xule05$ javap -v Test
Classfile /Users/xule05/test2019/ASM/boke/Test.class
Last modified 2019-1-14; size 182 bytes
MD5 checksum f22f52551c287057ed6d62d392d5647e
Compiled from "Test.java"
public class Test
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#10 // java/lang/Object."<init>":()V
#2 = Class #11 // Test
#3 = Class #12 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 SourceFile
#9 = Utf8 Test.java
#10 = NameAndType #4:#5 // "<init>":()V
#11 = Utf8 Test
#12 = Utf8 java/lang/Object
{
public Test();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
}
SourceFile: "Test.java"
2.常量池项 (cp_info) 的结构
常量池中的每一项常量都是一个表,JDK1.7以上版本共有14种不同的结构。这14种表都有一个共同特点,就是表开始的第一个位置是一个u1类型的标志位(tag,取值见下表),代表当前常量属于哪个常量类型。
类型 | tag | 描述 |
---|---|---|
Utf8 | 1 | UTF-8编码的Unicode字符串 |
Integer | 3 | int类型字面值 |
Float | 4 | float类型字面值 |
Long | 5 | long类型字面值 |
Double | 6 | double类型字面值 |
Class | 7 | 对一个类或接口的符号引用 |
String | 8 | String类型字面值 |
Fieldref | 9 | 对一个字段的符号引用 |
Methodref | 10 | 对一个类中声明的方法的符号引用 |
InterfaceMethodref | 11 | 对一个接口中声明的方法的符号引用 |
NameAndType | 12 | 字段或方法的部分符号引用 |
MethodHandle | 15 | 表示方法句柄 |
MethodType | 16 | 标识方法类型 |
InvokeDynamic | 18 | 表示一个动态方法调用点 |
每一个常量池项(cp_info) 都会相应记录着class文件里的某中类型的字面量。
3. 两种典型常量类型的表结构。
Class型常量的结构:
类型 | 名称 | 数量 |
---|---|---|
u1 | tag | 1 |
u2 | name_index | 1 |
tag 是标志位,用于区分常量类型;name_index 是一个索引值,指向常量池中的一个Utf8类型的常量,此常量代表这个类的全限定名。
Utf8型常量的结构:
类型 | 名称 | 数量 |
---|---|---|
u1 | tag | 1 |
u2 | length | 1 |
u1 | bytes | length |
下图显示了Class 类型常量与Utf8类型常量的关系:
![](https://img.haomeiwen.com/i13935704/61a739efe9d150d8.png)
网友评论