先準備一個簡單的java文件
public class Person {
private String name = "jack";
private int age;
private final double salary = 100;
private static String address;
private final static String hobby = "programming";
private static Object obj = new Object();
public void say(){
System.out.println("person say ...");
}
public static int calc(int op1,int op2){
op1 =3;
int result = op1 + op2;
Object object = new Object();
return result;
}
public static void main(String[] args) {
calc(1,2);
}
}
經過javac命令編譯後得到一個class文件,用UE編輯器打開後得到的class文件格式是如下這樣的
從https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html 的官網可以看到,class文件的結構是由以下的格式進行排列的,u1,u2,u4,u8分別代表1個字節,2個字節,4個字節,8個字節,以“_info”結尾的則稱爲表。class文件的順序,長度都是都是固定,不可以隨便變動
對應中文版本如下
class文件的第一個首先是魔數,魔數佔4個字節,也就是CA FE BA BE,作用是確定文件是否爲一個能被虛擬機識別的class文件 ,魔數之後就是次版本號(即00 00);主版本號(00 34);
各個版本的對應關係,本例中00 34也就是對應的是jdk1.8,也就是說是由jdk1.8編譯的。
常量池數量(00 3A),轉換爲十進制就是58,也就是說有58個常量,
constant_pool=constant_pool_count-1,本例中也就是常量有57個,我們可以通過javap -v Person.class命令得到如下反編譯之後的結果,可以看到Constant pool是從1到57的
Classfile /E:/project/study/src/main/java/com/sample/study/test/Person.class
Last modified 2020-5-21; size 911 bytes
MD5 checksum 934fb0bd52076255f9a7e34b641c3476
Compiled from "Person.java"
public class com.sample.study.test.Person
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #10.#38 // java/lang/Object."<init>":()V
#2 = String #39 // jack
#3 = Fieldref #13.#40 // com/sample/study/test/Person.name:Ljava/lang/String;
#4 = Double 100.0d
#6 = Fieldref #13.#41 // com/sample/study/test/Person.salary:D
#7 = Fieldref #42.#43 // java/lang/System.out:Ljava/io/PrintStream;
#8 = String #44 // person say ...
#9 = Methodref #45.#46 // java/io/PrintStream.println:(Ljava/lang/String;)V
#10 = Class #47 // java/lang/Object
#11 = Methodref #13.#48 // com/sample/study/test/Person.calc:(II)I
#12 = Fieldref #13.#49 // com/sample/study/test/Person.obj:Ljava/lang/Object;
#13 = Class #50 // com/sample/study/test/Person
#14 = Utf8 name
#15 = Utf8 Ljava/lang/String;
#16 = Utf8 age
#17 = Utf8 I
#18 = Utf8 salary
#19 = Utf8 D
#20 = Utf8 ConstantValue
#21 = Utf8 address
#22 = Utf8 hobby
#23 = String #51 // programming
#24 = Utf8 obj
#25 = Utf8 Ljava/lang/Object;
#26 = Utf8 <init>
#27 = Utf8 ()V
#28 = Utf8 Code
#29 = Utf8 LineNumberTable
#30 = Utf8 say
#31 = Utf8 calc
#32 = Utf8 (II)I
#33 = Utf8 main
#34 = Utf8 ([Ljava/lang/String;)V
#35 = Utf8 <clinit>
#36 = Utf8 SourceFile
#37 = Utf8 Person.java
#38 = NameAndType #26:#27 // "<init>":()V
#39 = Utf8 jack
#40 = NameAndType #14:#15 // name:Ljava/lang/String;
#41 = NameAndType #18:#19 // salary:D
#42 = Class #52 // java/lang/System
#43 = NameAndType #53:#54 // out:Ljava/io/PrintStream;
#44 = Utf8 person say ...
#45 = Class #55 // java/io/PrintStream
#46 = NameAndType #56:#57 // println:(Ljava/lang/String;)V
#47 = Utf8 java/lang/Object
#48 = NameAndType #31:#32 // calc:(II)I
#49 = NameAndType #24:#25 // obj:Ljava/lang/Object;
#50 = Utf8 com/sample/study/test/Person
#51 = Utf8 programming
#52 = Utf8 java/lang/System
#53 = Utf8 out
#54 = Utf8 Ljava/io/PrintStream;
#55 = Utf8 java/io/PrintStream
#56 = Utf8 println
#57 = Utf8 (Ljava/lang/String;)V
{
public com.sample.study.test.Person();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2 // String jack
7: putfield #3 // Field name:Ljava/lang/String;
10: aload_0
11: ldc2_w #4 // double 100.0d
14: putfield #6 // Field salary:D
17: return
LineNumberTable:
line 3: 0
line 4: 4
line 6: 10
public void say();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #8 // String person say ...
5: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 11: 0
line 12: 8
public static int calc(int, int);
descriptor: (II)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=2
0: iconst_3
1: istore_0
2: iload_0
3: iload_1
4: iadd
5: istore_2
6: new #10 // class java/lang/Object
9: dup
10: invokespecial #1 // Method java/lang/Object."<init>":()V
13: astore_3
14: iload_2
15: ireturn
LineNumberTable:
line 14: 0
line 15: 2
line 16: 6
line 17: 14
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: iconst_1
1: iconst_2
2: invokestatic #11 // Method calc:(II)I
5: pop
6: return
LineNumberTable:
line 20: 0
line 21: 6
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=2, locals=0, args_size=0
0: new #10 // class java/lang/Object
3: dup
4: invokespecial #1 // Method java/lang/Object."<init>":()V
7: putstatic #12 // Field obj:Ljava/lang/Object;
10: return
LineNumberTable:
line 9: 0
}
SourceFile: "Person.java"
access_flags:訪問標誌,主要標記的是接口或者類的信息,接口類型等