java class文件详解

来源:互联网 发布:mac需要清理软件 编辑:程序博客网 时间:2024/05/22 10:36

Java Class文件结构信息:


ClassFile {u4 magic;                                            //模数u2 minor_version;                                   //次版本号u2 major_version;                                  //主版本号u2 constant_pool_count;                           //常量池大小cp_info constant_pool[constant_pool_count-1];    //常量池u2 access_flags;                                //类和接口层次的访问标志(通过|运算得到)u2 this_class;                                 //类索引(指向常量池中的类常量)u2 super_class;                               //父类索引(指向常量池中的类常量)u2 interfaces_count;                         //接口索引计数器u2 interfaces[interfaces_count];            //接口索引集合u2 fields_count;                           //字段数量计数器field_info fields[fields_count];          //字段表集合u2 methods_count;                        //方法数量计数器method_info methods[methods_count];     //方法表集合u2 attributes_count;                   //属性个数attribute_info attributes[attributes_count];             //属性表}

1  代码实例:


                地址:   https://github.com/pantherproject/jvm-practice/tree/master/src/main/java/com/panther/jvm



用二进制打开文件:


 hexdump -C Sub.class 00000000  ca fe ba be 00 00 00 34  00 3b 0a 00 0a 00 28 09  |.......4.;....(.|00000010  00 09 00 29 09 00 09 00  2a 09 00 09 00 2b 09 00  |...)....*....+..|00000020  2c 00 2d 08 00 2e 0a 00  2f 00 30 08 00 31 07 00  |,.-...../.0..1..|00000030  32 07 00 33 07 00 34 07  00 35 01 00 06 73 75 62  |2..3..4..5...sub|00000040  49 6e 74 01 00 01 49 01  00 09 73 75 62 53 74 72  |Int...I...subStr|00000050  69 6e 67 01 00 12 4c 6a  61 76 61 2f 6c 61 6e 67  |ing...Ljava/lang|00000060  2f 53 74 72 69 6e 67 3b  01 00 09 73 75 62 4f 62  |/String;...subOb|00000070  6a 65 63 74 01 00 12 4c  6a 61 76 61 2f 6c 61 6e  |ject...Ljava/lan|00000080  67 2f 4f 62 6a 65 63 74  3b 01 00 06 3c 69 6e 69  |g/Object;...<ini|00000090  74 3e 01 00 03 28 29 56  01 00 04 43 6f 64 65 01  |t>...()V...Code.|000000a0  00 0f 4c 69 6e 65 4e 75  6d 62 65 72 54 61 62 6c  |..LineNumberTabl|000000b0  65 01 00 09 67 65 74 53  75 62 49 6e 74 01 00 03  |e...getSubInt...|000000c0  28 29 49 01 00 09 73 65  74 53 75 62 49 6e 74 01  |()I...setSubInt.|000000d0  00 04 28 49 29 56 01 00  0c 67 65 74 53 75 62 53  |..(I)V...getSubS|000000e0  74 72 69 6e 67 01 00 14  28 29 4c 6a 61 76 61 2f  |tring...()Ljava/|000000f0  6c 61 6e 67 2f 53 74 72  69 6e 67 3b 01 00 0c 73  |lang/String;...s|00000100  65 74 53 75 62 53 74 72  69 6e 67 01 00 15 28 4c  |etSubString...(L|00000110  6a 61 76 61 2f 6c 61 6e  67 2f 53 74 72 69 6e 67  |java/lang/String|00000120  3b 29 56 01 00 0c 67 65  74 53 75 62 4f 62 6a 65  |;)V...getSubObje|00000130  63 74 01 00 14 28 29 4c  6a 61 76 61 2f 6c 61 6e  |ct...()Ljava/lan|00000140  67 2f 4f 62 6a 65 63 74  3b 01 00 0c 73 65 74 53  |g/Object;...setS|00000150  75 62 4f 62 6a 65 63 74  01 00 15 28 4c 6a 61 76  |ubObject...(Ljav|00000160  61 2f 6c 61 6e 67 2f 4f  62 6a 65 63 74 3b 29 56  |a/lang/Object;)V|00000170  01 00 06 69 6e 74 65 72  43 01 00 06 69 6e 74 65  |...interC...inte|00000180  72 42 01 00 15 28 49 29  4c 6a 61 76 61 2f 6c 61  |rB...(I)Ljava/la|00000190  6e 67 2f 53 74 72 69 6e  67 3b 01 00 0a 53 6f 75  |ng/String;...Sou|000001a0  72 63 65 46 69 6c 65 01  00 08 53 75 62 2e 6a 61  |rceFile...Sub.ja|000001b0  76 61 0c 00 13 00 14 0c  00 0d 00 0e 0c 00 0f 00  |va..............|000001c0  10 0c 00 11 00 12 07 00  36 0c 00 37 00 38 01 00  |........6..7.8..|000001d0  11 74 68 65 20 69 6e 74  65 72 43 20 69 6e 20 53  |.the interC in S|000001e0  75 62 07 00 39 0c 00 3a  00 1e 01 00 11 74 68 65  |ub..9..:.....the|000001f0  20 69 6e 74 65 72 42 20  69 6e 20 53 75 62 01 00  | interB in Sub..|00000200  13 63 6f 6d 2f 70 61 6e  74 68 65 72 2f 6a 76 6d  |.com/panther/jvm|00000210  2f 53 75 62 01 00 14 63  6f 6d 2f 70 61 6e 74 68  |/Sub...com/panth|00000220  65 72 2f 6a 76 6d 2f 42  61 73 65 01 00 16 63 6f  |er/jvm/Base...co|00000230  6d 2f 70 61 6e 74 68 65  72 2f 6a 76 6d 2f 49 6e  |m/panther/jvm/In|00000240  74 65 72 42 01 00 16 63  6f 6d 2f 70 61 6e 74 68  |terB...com/panth|00000250  65 72 2f 6a 76 6d 2f 49  6e 74 65 72 43 01 00 10  |er/jvm/InterC...|00000260  6a 61 76 61 2f 6c 61 6e  67 2f 53 79 73 74 65 6d  |java/lang/System|00000270  01 00 03 6f 75 74 01 00  15 4c 6a 61 76 61 2f 69  |...out...Ljava/i|00000280  6f 2f 50 72 69 6e 74 53  74 72 65 61 6d 3b 01 00  |o/PrintStream;..|00000290  13 6a 61 76 61 2f 69 6f  2f 50 72 69 6e 74 53 74  |.java/io/PrintSt|000002a0  72 65 61 6d 01 00 07 70  72 69 6e 74 6c 6e 00 21  |ream...println.!|000002b0  00 09 00 0a 00 02 00 0b  00 0c 00 03 00 02 00 0d  |................|000002c0  00 0e 00 00 00 0a 00 0f  00 10 00 00 00 0a 00 11  |................|000002d0  00 12 00 00 00 09 00 01  00 13 00 14 00 01 00 15  |................|000002e0  00 00 00 1d 00 01 00 01  00 00 00 05 2a b7 00 01  |............*...|000002f0  b1 00 00 00 01 00 16 00  00 00 06 00 01 00 00 00  |................|00000300  06 00 01 00 17 00 18 00  01 00 15 00 00 00 1d 00  |................|00000310  01 00 01 00 00 00 05 2a  b4 00 02 ac 00 00 00 01  |.......*........|00000320  00 16 00 00 00 06 00 01  00 00 00 0f 00 01 00 19  |................|00000330  00 1a 00 01 00 15 00 00  00 22 00 02 00 02 00 00  |........."......|00000340  00 06 2a 1b b5 00 02 b1  00 00 00 01 00 16 00 00  |..*.............|00000350  00 0a 00 02 00 00 00 13  00 05 00 14 00 09 00 1b  |................|00000360  00 1c 00 01 00 15 00 00  00 1c 00 01 00 00 00 00  |................|00000370  00 04 b2 00 03 b0 00 00  00 01 00 16 00 00 00 06  |................|00000380  00 01 00 00 00 17 00 09  00 1d 00 1e 00 01 00 15  |................|00000390  00 00 00 21 00 01 00 01  00 00 00 05 2a b3 00 03  |...!........*...|000003a0  b1 00 00 00 01 00 16 00  00 00 0a 00 02 00 00 00  |................|000003b0  1b 00 04 00 1c 00 09 00  1f 00 20 00 01 00 15 00  |.......... .....|000003c0  00 00 1c 00 01 00 00 00  00 00 04 b2 00 04 b0 00  |................|000003d0  00 00 01 00 16 00 00 00  06 00 01 00 00 00 1f 00  |................|000003e0  09 00 21 00 22 00 01 00  15 00 00 00 21 00 01 00  |..!.".......!...|000003f0  01 00 00 00 05 2a b3 00  04 b1 00 00 00 01 00 16  |.....*..........|00000400  00 00 00 0a 00 02 00 00  00 23 00 04 00 24 00 01  |.........#...$..|00000410  00 23 00 14 00 01 00 15  00 00 00 25 00 02 00 01  |.#.........%....|00000420  00 00 00 09 b2 00 05 12  06 b6 00 07 b1 00 00 00  |................|00000430  01 00 16 00 00 00 0a 00  02 00 00 00 28 00 08 00  |............(...|00000440  29 00 01 00 24 00 25 00  01 00 15 00 00 00 1b 00  |)...$.%.........|00000450  01 00 02 00 00 00 03 12  08 b0 00 00 00 01 00 16  |................|00000460  00 00 00 06 00 01 00 00  00 2d 00 01 00 26 00 00  |.........-...&..|00000470  00 02 00 27                                       |...'|00000474




2. 魔数

作用:确定该文件是否是虚拟机可接受的class文件。java的魔数统一为 0xCAFEBABE (来源于一款咖啡)。

区域:文件第0~3字节。



3. 版本号


作用:表示class文件的版本,由minorversion和majorversion组成。

区域:文件第4~7字节。


51代表,jdk为1.7.0

需要注意的是java版本号是从45开始的,大版本发布,主版本号+1.高版本的jdk能向下兼容以前版本的class文件,但不兼容以后版本的class文件



4. 常量池

常量池的大小是不固定的,根据你的类中的常量的多少而定,所以在常量池的入口,放置了一个u2类型的表示常量池中常量个数的常量池容量计数器。计数器从1开始,第0位有特殊含义,表示指向常量池的索引值数据不引用任何一个常量池项目。池中的数据项就像数组一样是通过索引访问的。


我们可以清楚的看到,我们常量池中有63-1=62个常量。这些常量是什么呢?

要存放字面量Literal和符号引用Symbolic References。

字面量可能是文本字符串,或final的常量值。
符号引用包括以下:

  • 类或接口全限定名 Full Qualified Name
  • 字段名称和描述符 Descriptor
  • 方法名称和描述符


我们使用反编译工具查看一下:

javap -v Sub.class Classfile /opt/soft/project/54/jvm-practice/src/main/java/com/panther/jvm/Sub.class  Last modified 2017-8-23; size 1140 bytes  MD5 checksum e07ec896433041cc874ab7adabd1c7ac  Compiled from "Sub.java"public class com.panther.jvm.Sub extends com.panther.jvm.Base implements com.panther.jvm.InterB,com.panther.jvm.InterC  minor version: 0  major version: 52  flags: ACC_PUBLIC, ACC_SUPERConstant pool:   #1 = Methodref          #10.#40        // com/panther/jvm/Base."<init>":()V   #2 = Fieldref           #9.#41         // com/panther/jvm/Sub.subInt:I   #3 = Fieldref           #9.#42         // com/panther/jvm/Sub.subString:Ljava/lang/String;   #4 = Fieldref           #9.#43         // com/panther/jvm/Sub.subObject:Ljava/lang/Object;   #5 = Fieldref           #44.#45        // java/lang/System.out:Ljava/io/PrintStream;   #6 = String             #46            // the interC in Sub   #7 = Methodref          #47.#48        // java/io/PrintStream.println:(Ljava/lang/String;)V   #8 = String             #49            // the interB in Sub   #9 = Class              #50            // com/panther/jvm/Sub  #10 = Class              #51            // com/panther/jvm/Base  #11 = Class              #52            // com/panther/jvm/InterB  #12 = Class              #53            // com/panther/jvm/InterC  #13 = Utf8               subInt  #14 = Utf8               I  #15 = Utf8               subString  #16 = Utf8               Ljava/lang/String;  #17 = Utf8               subObject  #18 = Utf8               Ljava/lang/Object;  #19 = Utf8               <init>  #20 = Utf8               ()V  #21 = Utf8               Code  #22 = Utf8               LineNumberTable  #23 = Utf8               getSubInt  #24 = Utf8               ()I  #25 = Utf8               setSubInt  #26 = Utf8               (I)V  #27 = Utf8               getSubString  #28 = Utf8               ()Ljava/lang/String;  #29 = Utf8               setSubString  #30 = Utf8               (Ljava/lang/String;)V  #31 = Utf8               getSubObject  #32 = Utf8               ()Ljava/lang/Object;  #33 = Utf8               setSubObject  #34 = Utf8               (Ljava/lang/Object;)V  #35 = Utf8               interC  #36 = Utf8               interB  #37 = Utf8               (I)Ljava/lang/String;  #38 = Utf8               SourceFile  #39 = Utf8               Sub.java  #40 = NameAndType        #19:#20        // "<init>":()V  #41 = NameAndType        #13:#14        // subInt:I  #42 = NameAndType        #15:#16        // subString:Ljava/lang/String;  #43 = NameAndType        #17:#18        // subObject:Ljava/lang/Object;  #44 = Class              #54            // java/lang/System  #45 = NameAndType        #55:#56        // out:Ljava/io/PrintStream;  #46 = Utf8               the interC in Sub  #47 = Class              #57            // java/io/PrintStream  #48 = NameAndType        #58:#30        // println:(Ljava/lang/String;)V  #49 = Utf8               the interB in Sub  #50 = Utf8               com/panther/jvm/Sub  #51 = Utf8               com/panther/jvm/Base  #52 = Utf8               com/panther/jvm/InterB  #53 = Utf8               com/panther/jvm/InterC  #54 = Utf8               java/lang/System  #55 = Utf8               out  #56 = Utf8               Ljava/io/PrintStream;  #57 = Utf8               java/io/PrintStream  #58 = Utf8               println{  public com.panther.jvm.Sub();    descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=1, locals=1, args_size=1         0: aload_0         1: invokespecial #1                  // Method com/panther/jvm/Base."<init>":()V         4: return      LineNumberTable:        line 6: 0  public int getSubInt();    descriptor: ()I    flags: ACC_PUBLIC    Code:      stack=1, locals=1, args_size=1         0: aload_0         1: getfield      #2                  // Field subInt:I         4: ireturn      LineNumberTable:        line 15: 0  public void setSubInt(int);    descriptor: (I)V    flags: ACC_PUBLIC    Code:      stack=2, locals=2, args_size=2         0: aload_0         1: iload_1         2: putfield      #2                  // Field subInt:I         5: return      LineNumberTable:        line 19: 0        line 20: 5  public static java.lang.String getSubString();    descriptor: ()Ljava/lang/String;    flags: ACC_PUBLIC, ACC_STATIC    Code:      stack=1, locals=0, args_size=0         0: getstatic     #3                  // Field subString:Ljava/lang/String;         3: areturn      LineNumberTable:        line 23: 0  public static void setSubString(java.lang.String);    descriptor: (Ljava/lang/String;)V    flags: ACC_PUBLIC, ACC_STATIC    Code:      stack=1, locals=1, args_size=1         0: aload_0         1: putstatic     #3                  // Field subString:Ljava/lang/String;         4: return      LineNumberTable:        line 27: 0        line 28: 4  public static java.lang.Object getSubObject();    descriptor: ()Ljava/lang/Object;    flags: ACC_PUBLIC, ACC_STATIC    Code:      stack=1, locals=0, args_size=0         0: getstatic     #4                  // Field subObject:Ljava/lang/Object;         3: areturn      LineNumberTable:        line 31: 0  public static void setSubObject(java.lang.Object);    descriptor: (Ljava/lang/Object;)V    flags: ACC_PUBLIC, ACC_STATIC    Code:      stack=1, locals=1, args_size=1         0: aload_0         1: putstatic     #4                  // Field subObject:Ljava/lang/Object;         4: return      LineNumberTable:        line 35: 0        line 36: 4  public void interC();    descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=2, locals=1, args_size=1         0: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;         3: ldc           #6                  // String the interC in Sub         5: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V         8: return      LineNumberTable:        line 40: 0        line 41: 8  public java.lang.String interB(int);    descriptor: (I)Ljava/lang/String;    flags: ACC_PUBLIC    Code:      stack=1, locals=2, args_size=2         0: ldc           #8                  // String the interB in Sub         2: areturn      LineNumberTable:        line 45: 0}SourceFile: "Sub.java"

常量池中的项目类型如下:

  • CONSTANT_Utf8_info      tag标志位为1,   UTF-8编码的字符串
  • CONSTANT_Integer_info  tag标志位为3, 整形字面量
  • CONSTANT_Float_info     tag标志位为4, 浮点型字面量
  • CONSTANT_Long_info     tag标志位为5, 长整形字面量
  • CONSTANT_Double_info  tag标志位为6, 双精度字面量
  • CONSTANT_Class_info    tag标志位为7, 类或接口的符号引用
  • CONSTANT_String_info    tag标志位为8,字符串类型的字面量
  • CONSTANT_Fieldref_info  tag标志位为9,  字段的符号引用
  • CONSTANT_Methodref_info  tag标志位为10,类中方法的符号引用
  • CONSTANT_InterfaceMethodref_info tag标志位为11, 接口中方法的符号引用
  • CONSTANT_NameAndType_info tag 标志位为12,字段和方法的名称以及类型的符号引用

5. 类或接口访问标志

表示类或者接口方面的访问信息,比如Class表示的是类还是接口,是否为public、static、final等。,下面我们就来看看TestClass的访问标示。Class的访问标志值为0x0021:

根据前面说的各种访问标示的标志位,我们可以知道:0x0021=0x0001|0x0020 也即ACC_PUBLIC 和 ACC_SUPER为真,其中ACC_PUBLIC大家好理解,ACC_SUPER是jdk1.2之后编译的类都会带有的标志。



原创粉丝点击