一、Class文件:类的字节码文件,记录类的所有信息
package javase;
interface MyInterface {
int fun(String s);
}
class FatherClass {
public void fun1() {
System.out.println("call fun1()!");
}
}
public class TestClass extends FatherClass implements MyInterface {
private int val;
public TestClass(int val) {
this.val = val;
}
@Override
public int fun(String s) {
System.out.println(s);
return 0;
}
public static void main(String[] args) {
TestClass tc = new TestClass(100);
tc.fun("damon salvatore");
tc.fun1();
}
}
javap -v TestClass.class后(与直接二进制打开不一一对应!):
Classfile /D:/learn/ToBeTopJavaer/out/production/ToBeTopJavaer/javase/TestClass.class
Last modified 2020-6-16; size 907 bytes
MD5 checksum 4238be84864c2399027c3c5dba81c915
Compiled from "TestClass.java"
public class javase.TestClass extends javase.FatherClass implements javase.MyInterface
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #11.#35 // javase/FatherClass."<init>":()V
#2 = Fieldref #5.#36 // javase/TestClass.val:I
#3 = Fieldref #37.#38 // java/lang/System.out:Ljava/io/PrintStream;
#4 = Methodref #39.#40 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #41 // javase/TestClass
#6 = Methodref #5.#42 // javase/TestClass."<init>":(I)V
#7 = String #43 // damon salvatore
#8 = Methodref #5.#44 // javase/TestClass.fun:(Ljava/lang/String;)I
#9 = Methodref #5.#45 // javase/TestClass.fun1:()V
#10 = Methodref #11.#45 // javase/FatherClass.fun1:()V
#11 = Class #46 // javase/FatherClass
#12 = Class #47 // javase/MyInterface
#13 = Utf8 val
#14 = Utf8 I
#15 = Utf8 <init>
#16 = Utf8 (I)V
#17 = Utf8 Code
#18 = Utf8 LineNumberTable
#19 = Utf8 LocalVariableTable
#20 = Utf8 this
#21 = Utf8 Ljavase/TestClass;
#22 = Utf8 fun
#23 = Utf8 (Ljava/lang/String;)I
#24 = Utf8 s
#25 = Utf8 Ljava/lang/String;
#26 = Utf8 main
#27 = Utf8 ([Ljava/lang/String;)V
#28 = Utf8 args
#29 = Utf8 [Ljava/lang/String;
#30 = Utf8 tc
#31 = Utf8 fun1
#32 = Utf8 ()V
#33 = Utf8 SourceFile
#34 = Utf8 TestClass.java
#35 = NameAndType #15:#32 // "<init>":()V
#36 = NameAndType #13:#14 // val:I
#37 = Class #48 // java/lang/System
#38 = NameAndType #49:#50 // out:Ljava/io/PrintStream;
#39 = Class #51 // java/io/PrintStream
#40 = NameAndType #52:#53 // println:(Ljava/lang/String;)V
#41 = Utf8 javase/TestClass
#42 = NameAndType #15:#16 // "<init>":(I)V
#43 = Utf8 damon salvatore
#44 = NameAndType #22:#23 // fun:(Ljava/lang/String;)I
#45 = NameAndType #31:#32 // fun1:()V
#46 = Utf8 javase/FatherClass
#47 = Utf8 javase/MyInterface
#48 = Utf8 java/lang/System
#49 = Utf8 out
#50 = Utf8 Ljava/io/PrintStream;
#51 = Utf8 java/io/PrintStream
#52 = Utf8 println
#53 = Utf8 (Ljava/lang/String;)V
{
public javase.TestClass(int);
descriptor: (I)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: invokespecial #1 // Method javase/FatherClass."<init>":()V
4: aload_0
5: iload_1
6: putfield #2 // Field val:I
9: return
LineNumberTable:
line 16: 0
line 17: 4
line 18: 9
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this Ljavase/TestClass;
0 10 1 val I
public int fun(java.lang.String);
descriptor: (Ljava/lang/String;)I
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_1
4: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
7: iconst_0
8: ireturn
LineNumberTable:
line 22: 0
line 23: 7
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Ljavase/TestClass;
0 9 1 s Ljava/lang/String;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=2, args_size=1
0: new #5 // class javase/TestClass
3: dup
4: bipush 100
6: invokespecial #6 // Method "<init>":(I)V
9: astore_1
10: aload_1
11: ldc #7 // String damon salvatore
13: invokevirtual #8 // Method fun:(Ljava/lang/String;)I
16: pop
17: aload_1
18: invokevirtual #9 // Method fun1:()V
21: return
LineNumberTable:
line 27: 0
line 28: 10
line 29: 17
line 30: 21
LocalVariableTable:
Start Length Slot Name Signature
0 22 0 args [Ljava/lang/String;
10 12 1 tc Ljavase/TestClass;
public void fun1();
descriptor: ()V
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #10 // Method javase/FatherClass.fun1:()V
4: return
LineNumberTable:
line 13: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ljavase/TestClass;
}
SourceFile: "TestClass.java"
1. 魔术字
可能这种不会显示,直接查看字节码可以看到
2. 版本号
minor version: 0
major version: 52
3. 常量池
见下文详细分析
4. 访问标记
- 访问标志位
flags: ACC_PUBLIC, ACC_SUPER
-
JVM对访问标示符的规范如下:
5. this_class
this_class指向constant pool的索引值,该值必须是CONSTANT_Class_info类型
6. super_class
super_class存的是父类的名称在常量池里的索引
7. interfaces
实现接口个数及其名称在常量池里的索引
8. fields
成员变量个数和结构
9. methods
方法列表
10. attributes
对整个class文件所对应的类或者接口的描述
二、常量池
1. 内容
a. 字面量:字符串或者数值
#43 = Utf8 damon salvatore
b. 符号引用
类和接口的全限定名
- 格式
“L” + 类型的全限定名 + “;”
- 示例
#21 = Utf8 Ljavase/TestClass;
字段的名称和描述符
- 格式
- 示例
#36 = NameAndType #13:#14 // val:I
方法的名称和描述符
- 格式
(参数1类型 参数2类型 参数3类型 ...)返回值类型
- 示例
表示返回值为int,入参为String的函数,此处并没有函数名,具体会在后面Methodref指出
#23 = Utf8 (Ljava/lang/String;)I
#8 = Methodref #5.#44 // javase/TestClass.fun:(Ljava/lang/String;)I
2. 作用
- Class文件的资源仓库
参考
https://hollischuang.github.io/toBeTopJavaer/#/basics/java-basic/class-contant-pool