Class类文件的结构
作者:bin我们来看这样一个类
public class Test extends TestB{ public static Integer myData = TestB.data; public String normalMyData = "123"; public String normalMyDataEmpty; public static void main(String[] args) { System.out.println("333333"); } public String doTest(int date){ date = date + 1; System.out.println(date); return date + ""; } }
我们使用如下命令查看class文件的字节码内容
javap -verbose Test.class > Test.verbose
Test.verbose内容过长,我贴在文章末尾,我们先逐个来看
minor为次版本号,major为主版本号,版本号说明了当前的文件要用多少JDK版本以上的虚拟机才能执行
minor version: 0 major version: 52
Constant pool为常量池
Constant pool: ...
访问标识(access_flags)
标识接口、属性的访问权限
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
父类索引(super_class)
这里我门可以看到指向常量池的#11,#11是一个class,他指向一个utf-8的#47,包含类类的全名
super_class: #11 ... Constant pool: ... #11 = Class #47 ... #47 = Utf8 com/xiaoying/core/api/controller/TestB
字段表集合(field_info),其中字段集合会用到flags标识别权限,用descriptor标识类型
public static java.lang.Integer myData; descriptor: Ljava/lang/Integer; flags: (0x0009) ACC_PUBLIC, ACC_STATIC public java.lang.String normalMyData; descriptor: Ljava/lang/String; flags: (0x0001) ACC_PUBLIC public java.lang.String normalMyDataEmpty; descriptor: Ljava/lang/String; flags: (0x0001) ACC_PUBLIC
方法表集合(methods)
descriptor表示入参和反参类型,(I)表示入参Integer类型,括号后面表示返回类型
public java.lang.String doTest(int); descriptor: (I)Ljava/lang/String; flags: (0x0001) ACC_PUBLIC
属性表集合(attribute_info)
Class文件、字段表、方法表都可以携带自己的属性表集合,以描述某些场景专有的信息。
例如方法的代码,放在Code里面:
Code: ...
代码关联的行号放在LineNumberTable中:
LineNumberTable: line 14: 0 line 15: 4 line 16: 11
Test.verbose内容
Classfile /Users/zengbin/IdeaProjects/credit.guarantor_platform.core/core-portal/out/production/classes/Test.class Last modified 2021年4月1日; size 1179 bytes MD5 checksum 23ca2f79d1f7b785efa19f45ad0d7dd4 Compiled from "Test.java" public class com.zengbingo.core.api.controller.Test extends com.zengbingo.core.api.controller.TestB minor version: 0 major version: 52 flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #16 // com/zenbgingo/Test super_class: #17 // com/zenbgingo/TestB interfaces: 0, fields: 3, methods: 4, attributes: 1 Constant pool: #1 = Methodref #17.#41 // com/zenbgingo/TestB."<init>":()V #2 = String #42 // 123 #3 = Fieldref #16.#43 // com/zenbgingo/Test.normalMyData:Ljava/lang/String; #4 = Fieldref #44.#45 // java/lang/System.out:Ljava/io/PrintStream; #5 = String #46 // 333333 #6 = Methodref #47.#48 // java/io/PrintStream.println:(Ljava/lang/String;)V #7 = Methodref #47.#49 // java/io/PrintStream.println:(I)V #8 = Class #50 // java/lang/StringBuilder #9 = Methodref #8.#41 // java/lang/StringBuilder."<init>":()V #10 = Methodref #8.#51 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; #11 = String #52 // #12 = Methodref #8.#53 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #13 = Methodref #8.#54 // java/lang/StringBuilder.toString:()Ljava/lang/String; #14 = Fieldref #17.#55 // com/zenbgingo/TestB.data:Ljava/lang/Integer; #15 = Fieldref #16.#56 // com/zenbgingo/Test.myData:Ljava/lang/Integer; #16 = Class #57 // com/zenbgingo/Test #17 = Class #58 // com/zenbgingo/TestB #18 = Utf8 myData #19 = Utf8 Ljava/lang/Integer; #20 = Utf8 normalMyData #21 = Utf8 Ljava/lang/String; #22 = Utf8 normalMyDataEmpty #23 = Utf8 <init> #24 = Utf8 ()V #25 = Utf8 Code #26 = Utf8 LineNumberTable #27 = Utf8 LocalVariableTable #28 = Utf8 this #29 = Utf8 Lcom/zenbgingo/Test; #30 = Utf8 main #31 = Utf8 ([Ljava/lang/String;)V #32 = Utf8 args #33 = Utf8 [Ljava/lang/String; #34 = Utf8 doTest #35 = Utf8 (I)Ljava/lang/String; #36 = Utf8 date #37 = Utf8 I #38 = Utf8 <clinit> #39 = Utf8 SourceFile #40 = Utf8 Test.java #41 = NameAndType #23:#24 // "<init>":()V #42 = Utf8 123 #43 = NameAndType #20:#21 // normalMyData:Ljava/lang/String; #44 = Class #59 // java/lang/System #45 = NameAndType #60:#61 // out:Ljava/io/PrintStream; #46 = Utf8 333333 #47 = Class #62 // java/io/PrintStream #48 = NameAndType #63:#64 // println:(Ljava/lang/String;)V #49 = NameAndType #63:#65 // println:(I)V #50 = Utf8 java/lang/StringBuilder #51 = NameAndType #66:#67 // append:(I)Ljava/lang/StringBuilder; #52 = Utf8 #53 = NameAndType #66:#68 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #54 = NameAndType #69:#70 // toString:()Ljava/lang/String; #55 = NameAndType #71:#19 // data:Ljava/lang/Integer; #56 = NameAndType #18:#19 // myData:Ljava/lang/Integer; #57 = Utf8 com/zenbgingo/Test #58 = Utf8 com/zenbgingo/TestB #59 = Utf8 java/lang/System #60 = Utf8 out #61 = Utf8 Ljava/io/PrintStream; #62 = Utf8 java/io/PrintStream #63 = Utf8 println #64 = Utf8 (Ljava/lang/String;)V #65 = Utf8 (I)V #66 = Utf8 append #67 = Utf8 (I)Ljava/lang/StringBuilder; #68 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder; #69 = Utf8 toString #70 = Utf8 ()Ljava/lang/String; #71 = Utf8 data { public static java.lang.Integer myData; descriptor: Ljava/lang/Integer; flags: (0x0009) ACC_PUBLIC, ACC_STATIC public java.lang.String normalMyData; descriptor: Ljava/lang/String; flags: (0x0001) ACC_PUBLIC public java.lang.String normalMyDataEmpty; descriptor: Ljava/lang/String; flags: (0x0001) ACC_PUBLIC public com.zengbingo.core.api.controller.Test(); descriptor: ()V flags: (0x0001) ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method com/zenbgingo/TestB."<init>":()V 4: aload_0 5: ldc #2 // String 123 7: putfield #3 // Field normalMyData:Ljava/lang/String; 10: return LineNumberTable: line 3: 0 line 6: 4 LocalVariableTable: Start Length Slot Name Signature 0 11 0 this Lcom/zenbgingo/Test; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #5 // String 333333 5: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return LineNumberTable: line 10: 0 line 11: 8 LocalVariableTable: Start Length Slot Name Signature 0 9 0 args [Ljava/lang/String; public java.lang.String doTest(int); descriptor: (I)Ljava/lang/String; flags: (0x0001) ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: iload_1 1: iconst_1 2: iadd 3: istore_1 4: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 7: iload_1 8: invokevirtual #7 // Method java/io/PrintStream.println:(I)V 11: new #8 // class java/lang/StringBuilder 14: dup 15: invokespecial #9 // Method java/lang/StringBuilder."<init>":()V 18: iload_1 19: invokevirtual #10 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 22: ldc #11 // String 24: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 27: invokevirtual #13 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 30: areturn LineNumberTable: line 14: 0 line 15: 4 line 16: 11 LocalVariableTable: Start Length Slot Name Signature 0 31 0 this Lcom/zenbgingo/Test; 0 31 1 date I static {}; descriptor: ()V flags: (0x0008) ACC_STATIC Code: stack=1, locals=0, args_size=0 0: getstatic #14 // Field com/zenbgingo/TestB.data:Ljava/lang/Integer; 3: putstatic #15 // Field myData:Ljava/lang/Integer; 6: return LineNumberTable: line 5: 0 } SourceFile: "Test.java"