解析一個Java字節碼文件


1.ClassFile結構(Java虛擬機規范 4.1 )

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];
}

 

2. 一個示例程序的源代碼

 1 import java.util.logging.Logger;
 2 
 3 import sun.misc.BASE64Encoder;
 4 
 5 public class BASE64Util {
 6 
 7         private static Logger log = Logger.getLogger(BASE64Util.class.getName());
 8 
 9         public String encodeBase64(String message) {
10                 BASE64Encoder encoder = new BASE64Encoder();
11                 String result = encoder.encodeBuffer(message.getBytes());
12                 log.info(message);
13                 log.info(result);
14                 return result;
15         }
16         public static void main(String[] args) {
17                 BASE64Util base64Util = new BASE64Util();
18                 String message = "hello world";
19                 base64Util.encodeBase64(message);
20         }
21 }

 

3.編譯后的字節碼

 1 0000000: cafe babe 0000 0033 0038 0a00 0e00 1c07  .......3.8......
 2 0000010: 001d 0a00 0200 1c0a 001e 001f 0a00 0200  ................
 3 0000020: 2009 0008 0021 0a00 2200 2307 0024 0a00   ....!..".#..$..
 4 0000030: 0800 1c08 0025 0a00 0800 260a 0027 0028  .....%....&..'.(
 5 0000040: 0a00 2200 2907 002a 0100 036c 6f67 0100  ..".)..*...log..
 6 0000050: 1a4c 6a61 7661 2f75 7469 6c2f 6c6f 6767  .Ljava/util/logg
 7 0000060: 696e 672f 4c6f 6767 6572 3b01 0006 3c69  ing/Logger;...<i
 8 0000070: 6e69 743e 0100 0328 2956 0100 0443 6f64  nit>...()V...Cod
 9 0000080: 6501 000f 4c69 6e65 4e75 6d62 6572 5461  e...LineNumberTa
10 0000090: 626c 6501 000c 656e 636f 6465 4261 7365  ble...encodeBase
11 00000a0: 3634 0100 2628 4c6a 6176 612f 6c61 6e67  64..&(Ljava/lang
12 00000b0: 2f53 7472 696e 673b 294c 6a61 7661 2f6c  /String;)Ljava/l
13 00000c0: 616e 672f 5374 7269 6e67 3b01 0004 6d61  ang/String;...ma
14 00000d0: 696e 0100 1628 5b4c 6a61 7661 2f6c 616e  in...([Ljava/lan
15 00000e0: 672f 5374 7269 6e67 3b29 5601 0008 3c63  g/String;)V...<c
16 00000f0: 6c69 6e69 743e 0100 0a53 6f75 7263 6546  linit>...SourceF
17 0000100: 696c 6501 000f 4241 5345 3634 5574 696c  ile...BASE64Util
18 0000110: 2e6a 6176 610c 0011 0012 0100 1673 756e  .java........sun
19 0000120: 2f6d 6973 632f 4241 5345 3634 456e 636f  /misc/BASE64Enco
20 0000130: 6465 7207 002b 0c00 2c00 2d0c 002e 002f  der..+..,.-..../
21 0000140: 0c00 0f00 1007 0030 0c00 3100 3201 000a  .......0..1.2...
22 0000150: 4241 5345 3634 5574 696c 0100 0b68 656c  BASE64Util...hel
23 0000160: 6c6f 2077 6f72 6c64 0c00 1500 1607 0033  lo world.......3
24 0000170: 0c00 3400 350c 0036 0037 0100 106a 6176  ..4.5..6.7...jav
25 0000180: 612f 6c61 6e67 2f4f 626a 6563 7401 0010  a/lang/Object...
26 0000190: 6a61 7661 2f6c 616e 672f 5374 7269 6e67  java/lang/String
27 00001a0: 0100 0867 6574 4279 7465 7301 0004 2829  ...getBytes...()
28 00001b0: 5b42 0100 0c65 6e63 6f64 6542 7566 6665  [B...encodeBuffe
29 00001c0: 7201 0016 285b 4229 4c6a 6176 612f 6c61  r...([B)Ljava/la
30 00001d0: 6e67 2f53 7472 696e 673b 0100 186a 6176  ng/String;...jav
31 00001e0: 612f 7574 696c 2f6c 6f67 6769 6e67 2f4c  a/util/logging/L
32 00001f0: 6f67 6765 7201 0004 696e 666f 0100 1528  ogger...info...(
33 0000200: 4c6a 6176 612f 6c61 6e67 2f53 7472 696e  Ljava/lang/Strin
34 0000210: 673b 2956 0100 0f6a 6176 612f 6c61 6e67  g;)V...java/lang
35 0000220: 2f43 6c61 7373 0100 0767 6574 4e61 6d65  /Class...getName
36 0000230: 0100 1428 294c 6a61 7661 2f6c 616e 672f  ...()Ljava/lang/
37 0000240: 5374 7269 6e67 3b01 0009 6765 744c 6f67  String;...getLog
38 0000250: 6765 7201 002e 284c 6a61 7661 2f6c 616e  ger...(Ljava/lan
39 0000260: 672f 5374 7269 6e67 3b29 4c6a 6176 612f  g/String;)Ljava/
40 0000270: 7574 696c 2f6c 6f67 6769 6e67 2f4c 6f67  util/logging/Log
41 0000280: 6765 723b 0021 0008 000e 0000 0001 000a  ger;.!..........
42 0000290: 000f 0010 0000 0004 0001 0011 0012 0001  ................
43 00002a0: 0013 0000 001d 0001 0001 0000 0005 2ab7  ..............*.
44 00002b0: 0001 b100 0000 0100 1400 0000 0600 0100  ................
45 00002c0: 0000 0500 0100 1500 1600 0100 1300 0000  ................
46 00002d0: 4900 0200 0400 0000 21bb 0002 59b7 0003  I.......!...Y...
47 00002e0: 4d2c 2bb6 0004 b600 054e b200 062b b600  M,+......N...+..
48 00002f0: 07b2 0006 2db6 0007 2db0 0000 0001 0014  ....-...-.......
49 0000300: 0000 0016 0005 0000 000a 0008 000b 0011  ................
50 0000310: 000c 0018 000d 001f 000e 0009 0017 0018  ................
51 0000320: 0001 0013 0000 0036 0002 0003 0000 0012  .......6........
52 0000330: bb00 0859 b700 094c 120a 4d2b 2cb6 000b  ...Y...L..M+,...
53 0000340: 57b1 0000 0001 0014 0000 0012 0004 0000  W...............
54 0000350: 0011 0008 0012 000b 0013 0011 0014 0008  ................
55 0000360: 0019 0012 0001 0013 0000 0025 0001 0000  ...........%....
56 0000370: 0000 000d 1300 08b6 000c b800 0db3 0006  ................
57 0000380: b100 0000 0100 1400 0000 0600 0100 0000  ................
58 0000390: 0700 0100 1a00 0000 0200 1b              ...........

4. 字節碼說明

1)    

u4 magic 魔數 CAFEBABE

2) 

(u2,u2) (minor_version,major_version) jdk 1.7 

3) 

u2 constant_pool_count,0038 轉換成10進制為56,意味着常量池索引為1~55

4) 常量池解析

  4.1) 常量池數據結構

1 cp_info {
2     u1 tag;
3     u1 info[];
4 }

  4.2) 常量池的 tag 項說明

常量類型   值
CONSTANT_Class 7
CONSTANT_Fieldref 9
CONSTANT_Methodref 10
CONSTANT_InterfaceMethodref 11
CONSTANT_String       8
CONSTANT_Integer 3
CONSTANT_Float 4
CONSTANT_Long  5
CONSTANT_Double 6
CONSTANT_NameAndType 12
CONSTANT_Utf8 1
CONSTANT_MethodHandle 15
CONSTANT_MethodType 16
CONSTANT_InvokeDynamic 18
   

    常量池內容:

    

  1 [tom@localhost ch04]$ javap -verbose -c BASE64Util.class 
  2 Classfile /home/tom/mywork/hotspotws/ch04/BASE64Util.class
  3   Last modified Jun 12, 2016; size 923 bytes
  4   MD5 checksum 68b6eaa90d79a8133289624952dc4e3d
  5   Compiled from "BASE64Util.java"
  6 public class BASE64Util
  7   SourceFile: "BASE64Util.java"
  8   minor version: 0
  9   major version: 51
 10   flags: ACC_PUBLIC, ACC_SUPER
 11 Constant pool:
 12    #1 = Methodref          #14.#28        //  java/lang/Object."<init>":()V
 13    #2 = Class              #29            //  sun/misc/BASE64Encoder
 14    #3 = Methodref          #2.#28         //  sun/misc/BASE64Encoder."<init>":()V
 15    #4 = Methodref          #30.#31        //  java/lang/String.getBytes:()[B
 16    #5 = Methodref          #2.#32         //  sun/misc/BASE64Encoder.encodeBuffer:([B)Ljava/lang/String;
 17    #6 = Fieldref           #8.#33         //  BASE64Util.log:Ljava/util/logging/Logger;
 18    #7 = Methodref          #34.#35        //  java/util/logging/Logger.info:(Ljava/lang/String;)V
 19    #8 = Class              #36            //  BASE64Util
 20    #9 = Methodref          #8.#28         //  BASE64Util."<init>":()V
 21   #10 = String             #37            //  hello world
 22   #11 = Methodref          #8.#38         //  BASE64Util.encodeBase64:(Ljava/lang/String;)Ljava/lang/String;
 23   #12 = Methodref          #39.#40        //  java/lang/Class.getName:()Ljava/lang/String;
 24   #13 = Methodref          #34.#41        //  java/util/logging/Logger.getLogger:(Ljava/lang/String;)Ljava/util/logging/Logger;
 25   #14 = Class              #42            //  java/lang/Object
 26   #15 = Utf8               log
 27   #16 = Utf8               Ljava/util/logging/Logger;
 28   #17 = Utf8               <init>
 29   #18 = Utf8               ()V
 30   #19 = Utf8               Code
 31   #20 = Utf8               LineNumberTable
 32   #21 = Utf8               encodeBase64
 33   #22 = Utf8               (Ljava/lang/String;)Ljava/lang/String;
 34   #23 = Utf8               main
 35   #24 = Utf8               ([Ljava/lang/String;)V
 36   #25 = Utf8               <clinit>
 37   #26 = Utf8               SourceFile
 38   #27 = Utf8               BASE64Util.java
 39   #28 = NameAndType        #17:#18        //  "<init>":()V
 40   #29 = Utf8               sun/misc/BASE64Encoder
 41   #30 = Class              #43            //  java/lang/String
 42   #31 = NameAndType        #44:#45        //  getBytes:()[B
 43   #32 = NameAndType        #46:#47        //  encodeBuffer:([B)Ljava/lang/String;
 44   #33 = NameAndType        #15:#16        //  log:Ljava/util/logging/Logger;
 45   #34 = Class              #48            //  java/util/logging/Logger
 46   #35 = NameAndType        #49:#50        //  info:(Ljava/lang/String;)V
 47   #36 = Utf8               BASE64Util
 48   #37 = Utf8               hello world
 49   #38 = NameAndType        #21:#22        //  encodeBase64:(Ljava/lang/String;)Ljava/lang/String;
 50   #39 = Class              #51            //  java/lang/Class
 51   #40 = NameAndType        #52:#53        //  getName:()Ljava/lang/String;
 52   #41 = NameAndType        #54:#55        //  getLogger:(Ljava/lang/String;)Ljava/util/logging/Logger;
 53   #42 = Utf8               java/lang/Object
 54   #43 = Utf8               java/lang/String
 55   #44 = Utf8               getBytes
 56   #45 = Utf8               ()[B
 57   #46 = Utf8               encodeBuffer
 58   #47 = Utf8               ([B)Ljava/lang/String;
 59   #48 = Utf8               java/util/logging/Logger
 60   #49 = Utf8               info
 61   #50 = Utf8               (Ljava/lang/String;)V
 62   #51 = Utf8               java/lang/Class
 63   #52 = Utf8               getName
 64   #53 = Utf8               ()Ljava/lang/String;
 65   #54 = Utf8               getLogger
 66   #55 = Utf8               (Ljava/lang/String;)Ljava/util/logging/Logger;
 67 {
 68   public BASE64Util();
 69     flags: ACC_PUBLIC
 70     Code:
 71       stack=1, locals=1, args_size=1
 72          0: aload_0       
 73          1: invokespecial #1                  // Method java/lang/Object."<init>":()V
 74          4: return        
 75       LineNumberTable:
 76         line 5: 0
 77 
 78   public java.lang.String encodeBase64(java.lang.String);
 79     flags: ACC_PUBLIC
 80     Code:
 81       stack=2, locals=4, args_size=2
 82          0: new           #2                  // class sun/misc/BASE64Encoder
 83          3: dup           
 84          4: invokespecial #3                  // Method sun/misc/BASE64Encoder."<init>":()V
 85          7: astore_2      
 86          8: aload_2       
 87          9: aload_1       
 88         10: invokevirtual #4                  // Method java/lang/String.getBytes:()[B
 89         13: invokevirtual #5                  // Method sun/misc/BASE64Encoder.encodeBuffer:([B)Ljava/lang/String;
 90         16: astore_3      
 91         17: getstatic     #6                  // Field log:Ljava/util/logging/Logger;
 92         20: aload_1       
 93         21: invokevirtual #7                  // Method java/util/logging/Logger.info:(Ljava/lang/String;)V
 94         24: getstatic     #6                  // Field log:Ljava/util/logging/Logger;
 95         27: aload_3       
 96         28: invokevirtual #7                  // Method java/util/logging/Logger.info:(Ljava/lang/String;)V
 97         31: aload_3       
 98         32: areturn       
 99       LineNumberTable:
100         line 10: 0
101         line 11: 8
102         line 12: 17
103         line 13: 24
104         line 14: 31
105 
106   public static void main(java.lang.String[]);
107     flags: ACC_PUBLIC, ACC_STATIC
108     Code:
109       stack=2, locals=3, args_size=1
110          0: new           #8                  // class BASE64Util
111          3: dup           
112          4: invokespecial #9                  // Method "<init>":()V
113          7: astore_1      
114          8: ldc           #10                 // String hello world
115         10: astore_2      
116         11: aload_1       
117         12: aload_2       
118         13: invokevirtual #11                 // Method encodeBase64:(Ljava/lang/String;)Ljava/lang/String;
119         16: pop           
120         17: return        
121       LineNumberTable:
122         line 17: 0
123         line 18: 8
124         line 19: 11
125         line 20: 17
126 
127   static {};
128     flags: ACC_STATIC
129     Code:
130       stack=1, locals=0, args_size=0
131          0: ldc_w         #8                  // class BASE64Util
132          3: invokevirtual #12                 // Method java/lang/Class.getName:()Ljava/lang/String;
133          6: invokestatic  #13                 // Method java/util/logging/Logger.getLogger:(Ljava/lang/String;)Ljava/util/logging/Logger;
134          9: putstatic     #6                  // Field log:Ljava/util/logging/Logger;
135         12: return        
136       LineNumberTable:
137         line 7: 0
138 }

 

    4.2.1)

      

      #1 = Methodref          #14.#28        //  java/lang/Object."<init>":()V

      CONSTANT_Fieldref_info, CONSTANT_Methodref_info 和CONSTANT_InterfaceMethodref_info 結構

      字段,方法和接口方法由類似的結構表示: 

      字段:

1 CONSTANT_Fieldref_info {
2     u1 tag;
3     u2 class_index;
4     u2 name_and_type_index;
5 }

      方法:

1 CONSTANT_Methodref_info {
2     u1 tag;
3     u2 class_index;
4     u2 name_and_type_index;
5 }

      接口方法:

1 CONSTANT_InterfaceMethodref_info {
2     u1 tag;
3     u2 class_index;
4     u2 name_and_type_index;
5 }

這些結構各項的說明如下:

      • tag
        CONSTANT_Field_info結構的tag項的值為CONSTANT_Fieldref(9)。CONSTANT_Method_info結構的tag項的值為CONSTANT_Methodref(10)。CONSTANT_InterfaceMethodref_info結構的tag項的值為CONSTANT_InterfaceMethodref(11)。
      • class_index

         class_index項的值必須是對常量池的有效索引,常量池在該索引處的項必須是CONSTANT_Class_info結構,表示一個類或接口,當前字段或者方法是這個類或者接口的成員。

         CONSTANT_Method_info結構的class_index項的類型必須是類(不能是接口)。

         CONSTANT_InterfaceMethodref_info結構的class_index項的類型必須是接口(不能是類)。CONSTANT_Field_info結構的class_index項的類型既可以是類也可以是接口。

      • name_and_type_index

        name_and_type_index項的值必須是對常量池的有效索引,常量池在該索引處的項必須是CONSTANT_NameAndType_info結構,它表示當前字段或者方法的名字和描述符。

        在一個CONSANT_Fieldref_info結構中,給定的描述符必須是字段描述符。而CONSTANT_Methodref_info和CONSTANT_InterfaceMethodref_info中給定的描述符是方法描述符。

        如果一個CONSTANT_Methodref_info結構的方法名以"<"('\u003c')開頭,則說明這個方法名是特殊的<init>,即這個方法是實例初始化方法,它的返回類型必須為空。

     

       4.2.2)

        

         #2 = Class              #29            //  sun/misc/BASE64Encoder

         CONSTANT_Class_info 結構
        CONSTANT_Class_info 結構用於表示類或接口,格式如下:
        

1 CONSTANT_Class_info {
2     u1 tag;
3     u2 name_index;
4 }

       CONSTANT_Class_info 結構的項的說明:

      • tag

        CONSTANT_Class_info結構的tag項的值為CONSTANT_Class(7)。

      • name_index          

        name_index項的值,必須是對常量池的一個有效索引。常量池在該索引處的項必須是CONSTANT_Utf8_info結構,代表一個有效的類或接口二進制名稱的內部形式。
        因為數組也是由對象表示,所以字節碼指令anewarray和multianewarray可以通過常量池中的CONSTANT_Class_info結構來引用類數組。對於這些數組,類的名字就是數組類型的描述符。例如:

        表現二維int數組類型: int[][] 的名字是[[I

        表示一維Thread數組類型Thread[]的名字是:[Ljava/lang/Thread;

        一個有效的數組類型描述符中描述的數組維度必須小於等於255。

     4.2.3) 

     

       #3 = Methodref          #2.#28         //  sun/misc/BASE64Encoder."<init>":()V

     4.2.4) 

       

      #4 = Methodref          #30.#31        //  java/lang/String.getBytes:()[B

     4.2.5) 

      

      #5 = Methodref          #2.#32         //  sun/misc/BASE64Encoder.encodeBuffer:([B)Ljava/lang/String;

    4.2.6) 

        #6 = Fieldref #8.#33 // BASE64Util.log:Ljava/util/logging/Logger;

     4.2.7) 

    #7 = Methodref #34.#35 // java/util/logging/Logger.info:(Ljava/lang/String;)V

    4.2.8) 

    #8 = Class #36 // BASE64Util

    4.2.9) 

    #9 = Methodref #8.#28 // BASE64Util."<init>":()V

   4.2.10)   

   #10 = String             #37            //  hello world

    CONSTANT_String_info 結構
    CONSTANT_String_info 用於表示 java.lang.String 類型的常量對象,格式如下:
    

1 CONSTANT_String_info {
2     u1 tag;
3     u2 string_index;
4 }

     CONSTANT_String_info 結構各項的說明如下:

      • tag        

        CONSTANT_String_info結構的tag值為CONSTANT_String (8)

      • string_index

        string_index項的值必須是對常量池的有效索引,常量池在該索引處的項必須是CONSTANT_Utf8_info結構,表示一組Unicode碼點序列,這組Unicode碼點序列最終會被初始化一個String對象。
        

   4.2.11)    

       #11 = Methodref #8.#38 // BASE64Util.encodeBase64:(Ljava/lang/String;)Ljava/lang/String;

   4.2.12)   

      #12 = Methodref #39.#40 // java/lang/Class.getName:()Ljava/lang/String;

   4.2.13)  

      #13 = Methodref #34.#41 // java/util/logging/Logger.getLogger:(Ljava/lang/String;)Ljava/util/logging/Logger;

   4.2.14)  

       #14 = Class #42 // java/lang/Object

   4.2.15)   

       #15 = Utf8 log

      CONSTANT_Utf8_info 結構
      

1 CONSTANT_Utf8_info {
2     u1 tag;
3     u2 length;
4     u1 bytes[length];
5 }

    CONSTANT_Utf8_info 結構各項的說明如下:

      • tag

    CONSTANT_Utf8_info 結構的tag項的值為CONSTANT_Utf8(1)。

      • length

    length項的值指明了bytes[]數組的長度(注意,不能等同於當前結構所表示的String對象的長度),CONSTANT_Utf8_info結構中的內容是以length屬性確定長度而不是以null作為字符串的終結符。

    bytes[]

    bytes[]是表示字符串值的byte數組,bytes[]數組中每個成員的byte值都不會是0,也不在0xf0和0xff范圍內。

  4.2.16) 

    #16 = Utf8 Ljava/util/logging/Logger;

  

  4.2.17) 

    #17 = Utf8 <init>

  4.2.18) 

    #18 = Utf8 ()V

  4.2.19) 

    #19 = Utf8 Code

  4.2.20) 

    #20 = Utf8 LineNumberTable

  4.2.21) 

    #21 = Utf8 encodeBase64

  

  4.2.22) 

    #22 = Utf8 (Ljava/lang/String;)Ljava/lang/String;

  

  4.2.23) 

    #23 = Utf8 main

  4.2.24) 

    #24 = Utf8 ([Ljava/lang/String;)V

  

  4.2.25) 

     #25 = Utf8 <clinit>

   

  4.2.26) 

    #26 = Utf8 SourceFile

  

  4.2.27) 

    #27 = Utf8 BASE64Util.java

  

  4.2.28) 

    #28 = NameAndType #17:#18 // "<init>":()V

    CONSTANT_NameAndType_info 結構
    CONSTANT_NameAndType_info 結構用於表示字段或方法,但是CONSTANT_NameAndType_info結構沒有標識出它所屬的類或接口,格式如下:

    

1 CONSTANT_NameAndType_info {
2     u1 tag;
3     u2 name_index;
4     u2 descriptor_index;
5 }

CONSTANT_NameAndType_info 結構各項的說明如下:

        • tag

      CONSTANT_NameAndType_info結構的tag項的值為CONSTANT_NameAndType(12)。

        • name_index

      name_index項的值必須是對常量池的有效索引,常量池是在該索引處的項必須是CONSTANT_Utf8_info結構,這個結構要么表示特殊的方法名<init>,要么表示一個有效的字段或方法的非限定名(Unqualified Name)。

        • descriptor_index

      descriptor_index項的值必須是對常量池的有效索引,常量池在該索引處的項必須是CONSTANT_Utf8_info結構,這個結構表示一個有效的字段描述符或方法描述符。

 

    4.2.29) 

     #29 = Utf8 sun/misc/BASE64Encoder

 

    4.2.30) 

      #30 = Class #43 // java/lang/String

    

    4.2.31)  

      #31 = NameAndType #44:#45 // getBytes:()[B

     

    4.2.32) 

      #32 = NameAndType #46:#47 // encodeBuffer:([B)Ljava/lang/String;

    

   4.2.33) 

      #33 = NameAndType #15:#16 // log:Ljava/util/logging/Logger;

    

   4.2.34) 

      #34 = Class #48 // java/util/logging/Logger

  

  4.2.35) 

      #35 = NameAndType #49:#50 // info:(Ljava/lang/String;)V

  

  4.2.36) 

      #36 = Utf8 BASE64Util

  

  4.2.37) 

      #37 = Utf8 hello world

  

  4.2.38) 

     #38 = NameAndType #21:#22 // encodeBase64:(Ljava/lang/String;)Ljava/lang/String;

  

  4.2.39) 

    #39 = Class #51 // java/lang/Class

  

  4.2.40) 

    #40 = NameAndType #52:#53 // getName:()Ljava/lang/String;

  

  4.2.41) 

    #41 = NameAndType #54:#55 // getLogger:(Ljava/lang/String;)Ljava/util/logging/Logger;

  

  4.2.42) 

    #42 = Utf8 java/lang/Object

  

  4.2.43) 

    #43 = Utf8 java/lang/String

 

  4.2.44) 

    #44 = Utf8 getBytes

 

  4.2.45) 

     #45 = Utf8 ()[B

  

  4.2.46) 

    #46 = Utf8 encodeBuffer

  

  4.2.47) 

     #47 = Utf8 ([B)Ljava/lang/String;

  

  4.2.48) 

    #48 = Utf8 java/util/logging/Logger

  

  4.2.49) 

    #49 = Utf8 info

 

  4.2.50)

    #50 = Utf8 (Ljava/lang/String;)V

  

  4.2.51) 

    #51 = Utf8 java/lang/Class

  

  4.2.52) 

     #52 = Utf8 getName

  

  4.2.53) 

    #53 = Utf8 ()Ljava/lang/String;

 

  4.2.54) 

    #54 = Utf8 getLogger

  4.2.55) 

     #55 = Utf8 (Ljava/lang/String;)Ljava/util/logging/Logger;

 

5)  u2 access_flags  

  

標志名 設置后的語義 設置者
ACC_PUBLIC 0x0001 public類型 類和接口
ACC_FINAL 0x0010 類為final 只有類
ACC_SUPER 0x0020 使用新型的invokespecial語義 類和接口
ACC_INTERFACE 0x0200 接口類型,不是類類型 所有的接口,部分類
ACC_ABSTRACT 0X0400 abstract類型 所有的接口,部分類

 

6)  u2 this_class;

 

  #8 = Class #36 // BASE64Util

 

7) u2 super_class;

#14 = Class              #42            //  java/lang/Object

 8) u2 interfaces_count;

 

 

9) u2 interfaces[interfaces_count];

 

10) u2 fields_count;

 

11)  field_info fields[fields_count];

每個字段(Field)都由field_info結構所定義,在同一個Class文件中,不會有兩個字段同時具有相同的字段名和描述符。

field_info結構格式如下:

1 field_info {
2     u2 access_flags;
3     u2 name_index;
4     u2 descriptor_index;
5     u2 attributes_count;
6     attribute_info attributes[attributes_count];
7 }

field_info 結構各項說明如下:

  • access_flags

  access_flags項的值是用於定義字段被訪問權限和基礎屬性的掩碼標志。

  access_flags的取值范圍和相應含義見下表所示。

標記名 說明
ACC_PUBLIC 0x0001 public,表示字段可以從任何包訪問。
ACC_PRIVATE 0x0002 private,表示字段僅能該類自身調用。
ACC_PROTECTED 0x0004 protected,表示字段可以被子類調用。
ACC_STATIC 0x0008 static,表示靜態字段。
ACC_FINAL 0X0010 final,表示字段定義后值無法修改
ACC_VOLATILE 0X0040 volatile,表示字段是易變的
ACC_TRANSIENT 0x0080 transient,表示字段不會被序列化
ACC_SYNTHETIC 0x1000 表示字段由編譯器自動產生
ACC_ENUM 0x4000 enum,表示字段為枚舉類型
  • name_index

  name_index項的值必須是對常量池的一個有效索引。常量池在該索引處的項必須是CONSTANT_Utf8_info結構,表示一個有效的字段的非全限定名。

  •  descriptor_index

  descriptor_index項的值必須是對常量池的一個有效索引。常量池在該索引處的項必須是CONSTANT_Utf8_info結構,表示一at個有效的字段段描述符。

  • attribute_count

  attribute_count項的值表示當前字段的附加屬性的數量。

  • attributes[]

  attributes表的每一個成員的值都必須是attribute結構,一個字段可以有任意個關聯屬性。jdk7規范中,attributes表可出現的成員有:

  ConstantValue,Synthetic,Signature,Deprecated,RuntimeVisiableAnnotations和RuntimeInvisibleAnnotations。

  Java虛擬機實現必須正確的識別和讀取field_info結構的attributes表中的ConstantValue屬性。如果Java虛擬機實現支持版本號為49.0或者更高的Class文件,那么它必須正確的識別和讀取這些Class文件中的Signature,RuntimeVisiableAnnotations和RuntimeInvisiableAnnotations結構。

  所有Java虛擬機實現都必須默認忽略field_info結構中的attributes表所不可識別的成員。規范中沒有定義的屬性不可影響Class文件中的語義,它們只能提供附加描述信息。

  000a = 0080&0020 = ACC_STATIC&ACC_PRIVATE 

  000f= #15 = Utf8 log

  0010=#16 = Utf8 Ljava/util/logging/Logger;

  0000

 

12) u2 methods_count;

 

13) method_info methods[methods_count];

  所有方法(Method),包括實例初始化方法和類初始化方法在內,都由method_info結構所定義。在一個Class文件中,不會有兩個方法同時具有相同的方法名和描述符。

  method_info結構格式如下:

method_info {
    u2 access_flags;
    u2 name_index;
    u2 descriptor_index;
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}

method_info結構各項的說明如下:

  • access_flags

  access_flags項的值是用於定義當前方法的訪問權限和基本屬性的掩碼標識,access_flags的取值范圍和相應含義見下表所示。

標記名 說明
ACC_PUBLIC 0x0001 public,方法可以從包外訪問
ACC_PRIVATE 0X0002 private,方法只能本類中訪問
ACC_PROTECTED 0X0004 protected,方法在自身和子類中可見
ACC_STATIC 0x0008 static,靜態方法
ACC_FINAL 0x0010 final,方法不能被重寫
ACC_SYNCHORNIZED 0X0020 synchornized,方法由管程同步
ACC_BRIDGE 0x0040 bridge,方法由編譯器產生
ACC_VARARGS 0x0080 標識方法帶有變長參數
ACC_NATIVE 0x0100 native,方法引用非java語言的本地方法
ACC_ABSTRACT 0x0400 abstract,方法沒有具體實現
ACC_STRICT 0x0800 strictfp,方法使用FP-strict浮點格式  
ACC_SYNTHETIC 0x1000 方法在源文件中不出現,由編譯器產生

  ACC_VARARGS標志是用於說明方法在源碼層的參數列表是否變長的。如果是變長的,在編譯時,方法的ACC_VARARGS標志設置1,其余的方法ACC_VARARGS標志設置為0。

  ACC_BRIDGE標志用於說明這個方法是由編譯器生成的橋接方法。橋接方法是JDK1.5引入泛型后,為了使Java的泛型方法生成的字節碼和1.5版本前的字節碼兼容,由編譯器自動生成的方法。

  如果方法設置了ACC_SYNTHETIC標志,則說明這個方法是由編譯器生成的並且不會在源代碼中出現。

 

  • name_index

  name_index的值必須是對常量池的一個有效索引。常量池在該索引處的項必須是CONSTANT_Utf8_info結構,它要么表示初始化方法的名字(<init>或<clinit>),要么表示一個方法的有效的非全限定名。

 

  • descriptor_index

  descriptor_index項的值必須是對常量池的一個有效索引。常量池在該索引處的項必須是CONSTANT_Utf8_info結構,表示一個有效的方法描述符。

 

  • attributes_count

  attributes_count的項的值表示這個方法的附加屬性的數量。

  • attributes[]

  attributes表的每一個成員的值必須是attribute結構,一個方法可以有任意個與之相關的屬性。

  本規范所定義的method_info結構中,屬性表可出現的成員有:Code,Exceptions , Synthetic ,Signature ,Deprecated ,RuntimeVisiableAnnotations , RuntimeInvisiableAnnotations , RuntimeVisiableParameterAnnotations,RuntimeInvisiableParameterAnnotations和AnnotationDefault結構。

 

  Java虛擬機實現必須正確識別和讀取method_info結構中的屬性表的Code和Exception屬性。如果Java虛擬機實現支持的版本為49.0或更高的Class文件,那么它必須正確識別和讀取這些Class文件的Signature , RuntimeVisiableAnnotations , RuntimeInvisiableAnnotations , RuntimeVisiableParameterAnnotations , RuntimeInvisiableParameerAnnotations 和 AnnotationDefault屬性。  

  所有Java虛擬機實現必須默認忽略method_info結構中attributes表所不可識別的成員。沒有定義的屬性不可影響Class文件的語義,它們只能提供附加描述信息。

 

13.1) 

  access_flags (u2)= 0001 = public

  name_index(u2)=0011= #17 = Utf8 <init>

  descriptor_index=0012= #18 = Utf8 ()V

  attributes_count = 0001=1

  13.1.1) attributes[1]

  

  屬性(Attribute)在Class文件格式中的ClassFile結構、field_info結構,method_info結構和Code_attribute結構都有使用,所有屬性的通用格式如下:

1 attribute_info {
2     u2 attribute_name_index;
3     u4 attribute_length;
4     u1 info[attribute_length];
5 }

  對於任意屬性,attribute_name_index必須是對當前Class文件的常量池的有效16位無符號索引。常量池在該索引處的項必須是Constant_Utf8_info結構,表示當前屬性的名字。attribute_length的值給出了跟隨其后的字節的長度,這個長度不包括attribute_length和attribute_name_index項的6個字節。

  有些屬性因Class文件格式所需,已被預先定義好。這些屬性在下表中列出,同時,被列出的信息還包括它們首次出現的Class文件版本和Java SE版本號。在規范定義的環境中,也就是已包含這些預定義屬性的Class文件中,它們的屬性名稱被保留,不能再被屬性表中的其他自定義屬性所使用。

屬性名 JavaSE Class文件
ConstantValue 1.0.2 45.3
Code 1.0.2 45.3
StackMapTable 6   50.0
Exceptions 1.0.2 45.3
InnerClass 1.1 45.3
EnclosingMethod 5.0 49.0
Synthetic 1.1 45.3
Signature 5.0 49.0
SourceFile 1.0.2 45.3
SourceDebugExtension 5.0 49.0
LineNumberTable 1.0.2 45.3
LocalVariableTable 1.0.2 45.3
LocalVariableTypeTable 5.0 49.0
Deprecated 1.1 45.3
RuntimeVisiableAnnotations 5.0 49.0
RuntimeInvisiableAnnotations 5.0 49.0
RuntimeVisiableParameterAnnotations 5.0 49.0
RuntimeInvisiableParameterAnnotations 5.0 49.0
AnnotationDefault 5.0 49.0
BootstrapMethods 7 51.0
  •   Java虛擬機實現的Class文件加載器(Class File Reader)必須正確的識別和讀取ConstantValue,Code和Exception屬性;同樣,Java虛擬機也必須能正確的解析它們的語義。
  •   InnerClasses,EnclosingMethod和Synthetic屬性必須被Class文件加載器正確的識別並讀入,它們用於實現Java平台的類庫。
  •   如果Java虛擬機實現支持的Class版本號為49.0或者更高時,它的Class文件加載器必須能正確的識別並讀取Class文件中的RuntimeVisiableAnnotations,RuntimeInvisiableAnnotations,RuntimeVisiableParameterAnnotations,RuntimeInvisiableParameterAnnotations和AnnotationDefault屬性,它們用於實現Java平台類庫。
  • 如果Java虛擬機實現支持的Class文件的版本號為49.0或者更高時,它的Class文件加載器必須正確的識別和讀取Class文件中的Signature屬性。
  • 如果Java虛擬機實現支持的Class文件的版本號為50.0或者更高時,它的Class文件加載器必須正確的識別和讀取StackMapTable屬性。
  • 如果Java虛擬機實現支持的Class文件的版本號為51.0或者更高時,它的Class文件加載器必須正確的識別和讀取BootstrapMethods屬性。
  • 對於剩余的預定義屬性的使用不受限制,如果剩余的預定義屬性包含虛擬機可識別的信息,Class文件加載器就可以選擇使用這些信息,否則可以選擇忽略它們。

  u2(attribute_name_index)=0013=#19 = Utf8 Code

  u4(attribute_length)=0000001d=29

 Code屬性是一個變長屬性,位於method_info結構的屬性表。一個Code屬性只為唯一一個方法、實例初始化方法或類初始化方法保存Java虛擬機指令以及相關輔助信息。所有Java虛擬機實現都必須能識別Code屬性。如果方法被聲明為native或者abstract類型,那么對應的method_info結構不能有明確的Code屬性,其他情況下,method_info必須有明確的Code屬性。

  Code屬性的格式如下:

 

Code_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 max_stack;
    u2 max_locals;
    u4 code_length;
    u1 code[code_length];
    u2 exception_table_length;
    { u2 start_pc;
       u2 end_pc;
       u2 handler_pc;
       u2 catch_type;
    } exception_table[exception_table_length];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}
  • attribute_name_index:

  attribute_name_index項的值必須是對常量池的有效索引,常量池在該索引處的項必須是COSNTANT_Utf8_info結構,表示字符串Code。

  • attribute_length:

  attribute_length項的值表示當前屬性的長度,不包括開始的6個字節

  • max_stack

  max_stack項的值給出了當前方法的操作數棧在運行執行的任何時間點的最大深度。

  • max_locals

  max_locals項的值給出了分配在當前方法引用的局部變量表中的局部變量個數,包括調用此方法時,用於傳遞參數的局部變量。

  long和double型的局部變量的最大索引是max_locals-2,其他類型的局部變量的最大索引是max_locals-1。

  • code_length

  code_length項給出了當前方法的code[]數組的字節數,code_length的值必須大於0,即code[]數組不能為空。

  • code[]

  code[]數組給出了實現當前方法的Java虛擬機字節碼。

  code[]數組以按字節尋址的方式讀入機器內存,如果code[]數組的第一個字節是按以4字節邊界對齊的話,那么tableswitch和lookupswitch指令中所有涉及的32位偏移量也是按4字節長度對齊的。

  • exception_table_length

  exception_table_length的值給出了exception_table[]數組的成員個數。

  • exception_table[]

  exception_table[]數組的每個成員表示code[]數組中的一個異常處理器(ExceptionHandler)。exception_table[]數組中,異常處理順序是有意義的(不能隨意修改)。

  exception_table[]數組包含如下4項:

    •     start_pc和end_pc

  start_pc和end_pc兩項的值表明了異常處理器在code[]數組中的有效范圍。start_pc必須是當前code[]數組中某一指令的操作碼的有效索引,end_pc要么是對當前code[]數組中某一指令的操作碼的有效索引,要么等於code_length的值,即當前code[]數組的長度。start_pc的值必須比end_pc小。

  當程序計數器在范圍[start_pc,end_pc)內時,異常處理器就將生效。即設x為異常句柄的有效范圍內的值,x滿足start_pc≤x<end_pc。

  實際上,end_pc的值本身不屬於異常處理器的有效范圍這點屬於Java虛擬機歷史上的一個設計缺陷:如果Java虛擬機中的一個方法的code屬性的長度剛好是65535個字節,並且是以一個字節長度的指令結束,那么這條指令將不能被異常處理器所處理。不過編譯器可能通過限制方法、實例化方法或類初始化方法的code[]數組最大長度為65534,這樣可以間接彌補這個Bug。

    •     handler_pc

  handler_pc項表示一個異常處理器的起點,它的值必須同時是一個對當前code[]數組中某一指令的操作碼的有效索引

    •     catch_type

  如果catch_type項的值不為0,那么它必須是對常量池的一個有效索引,常量池在該處的索引必須是CONSTANT_Class_info結構,表示當前異常處理器指定需要的捕捉的異常類型。只有當拋出的異常是指定的類或者其子類的實例的時,異常處理器才會被調用。

  如果catch_type項的值如果為0,那么這個異常處理器將會在所有異常拋出時被調用。這可以用於實現finally語句。

  

  •   attributes_count

  attributes_count項的值給出了Code屬性中attributes表的成員的個數。

  •   attributes[]

  屬性表的每個成員的值必須是attribute結構。一個Code屬性可以有任意數量的可選屬性與之聯系。

  可能出現在Code屬性的屬性表中的成員只能是LineNumberTable,LocalVariableTable,LocalVariableTypeTable和StackMapTable屬性。

  如果一個Java虛擬機實現支持的Class文件版本號為50.0或更高,那么它必須正確的識別和讀取Code屬性的屬性表中出現的StackMapTable屬性。

  Java虛擬機實現必須自動忽略Code屬性的屬性表數組中出現的所有它不能識別的屬性。本規范中沒有定義的屬性不可影響Class文件語義,只能提供附加描述信息。

  

  u2(max_stack)=0001 (表示操作棧在運行時執行的任何時間點的最大深度。)

  u2(max_locals)=0001(在當前方法引用的局部變量表中的局部變量個數)

  u4(code_length)=00000005(當前方法的 code[]數組的字節數)

  code(5)

  2a=aload_0     this將會壓如操作數棧頂

  b70001    invokespecial 0001 

          #1 = Methodref #14.#28 // java/lang/Object."<init>":()V

  b1      return 

 

13.2) 

  u2(access_flags) = 0001 = public 

  u2(name_index)=0015= #21 = Utf8               encodeBase64

  u2(descriptor_index)=0016=#22 = Utf8               (Ljava/lang/String;)Ljava/lang/String;

   u2(attributes_count)=0001

  [  

    u2(attribute_name_index)=0013=#19 = Utf8               Code

    u4(attribute_length)=00000049

      [

        u2(max_stack)=0002

        u2(max_locals)=0004

        u4(code_length)=00000021

      ]

  ]

 

 bb 0002 new 0002

      #2 = Class              #29            //  sun/misc/BASE64Encoder

 59 dup (復制棧頂數值並將復制值壓入棧頂。)

 b7 0003 invokespecial 0003

    #3 = Methodref          #2.#28         //  sun/misc/BASE64Encoder."<init>":()V

 4d astore_2 

 2c aload_2

 2b aload_1

 b6 0004 invokevirtual 0004

    #4 = Methodref          #30.#31        //  java/lang/String.getBytes:()[B

 b6 0005 invokevirtual 0005

     #5 = Methodref          #2.#32         //  sun/misc/BASE64Encoder.encodeBuffer:([B)Ljava/lang/String; 

 4e astore_3

 b2 0006   getstatic 0006

       #6 = Fieldref           #8.#33         //  BASE64Util.log:Ljava/util/logging/Logger;  

  2b aload_1

  b6 0007 invokespecial 0007

    #7 = Methodref          #34.#35        //  java/util/logging/Logger.info:(Ljava/lang/String;)V 

 

  b2 0006   getstatic 0006

       #6 = Fieldref           #8.#33         //  BASE64Util.log:Ljava/util/logging/Logger;  

 2d aload_3

 

  b6 0007 invokespecial 0007

    #7 = Methodref          #34.#35        //  java/util/logging/Logger.info:(Ljava/lang/String;)V 

 

 2d aload_3

 b0 areturn 

u2(exception_table_length) 0000

u2(attribute_count) 0001 

u2(attribute_name_index)=0014=#20 = Utf8               LineNumberTable

u4(attribue_length)=00000016

LineNumberTable屬性

  LineNumberTable屬性是可選變長屬性,位於Code結構的屬性表。它被調試器用於確定源碼行號表示的內容在JVM虛擬機的code數組中對應的部分。在Code屬性的屬性表中,LineNumberTable屬性可以按照任意屬性出現,此外,多個LineNumberTable屬性可以共同表示一個行號在源文件中表示的內容,即LineNumberTable屬性不需要與源文件行一一對應。

  LineNumberTable屬性格式如下:

1 LineNumberTable_attribute {
2     u2 attribute_name_index;
3     u4 attribute_length;
4     u2 line_number_table_length;
5     { 
6         u2 start_pc;  //start_pc 項的值必須是 code[]數組的一個索引, code[]數組在該索引處的字符
                表示源文件中新的行的起點。 start_pc 項的值必須小於當前 LineNumberTable
                屬性所在的 Code 屬性的 code_length 項的值。

7 u2 line_number; 8 } line_number_table[line_number_table_length]; 9 }

  u2(line_number_length)=0005 

   (0000,000a)

  (0008,000b)

  (0011,000c)

  (0018,000d)

  (001f,0000e)

 

 78   public java.lang.String encodeBase64(java.lang.String);
 79  flags: ACC_PUBLIC 80  Code: 81 stack=2, locals=4, args_size=2 82 0: new #2 // class sun/misc/BASE64Encoder 83 3: dup 84 4: invokespecial #3 // Method sun/misc/BASE64Encoder."<init>":()V 85 7: astore_2 86 8: aload_2 87 9: aload_1 88 10: invokevirtual #4 // Method java/lang/String.getBytes:()[B 89 13: invokevirtual #5 // Method sun/misc/BASE64Encoder.encodeBuffer:([B)Ljava/lang/String; 90 16: astore_3 91 17: getstatic #6 // Field log:Ljava/util/logging/Logger; 92 20: aload_1 93 21: invokevirtual #7 // Method java/util/logging/Logger.info:(Ljava/lang/String;)V 94 24: getstatic #6 // Field log:Ljava/util/logging/Logger; 95 27: aload_3 96 28: invokevirtual #7 // Method java/util/logging/Logger.info:(Ljava/lang/String;)V 97 31: aload_3 98 32: areturn 99  LineNumberTable: 100 line 10: 0 101 line 11: 8 102 line 12: 17 103 line 13: 24 104 line 14: 31

13.3) 

 

 u2(access_flag)=0009=0008&0001=static&public

 u2(name_index)=0017=#23 = Utf8               main

 u2(descriptor_index)=0018=#24 = Utf8               ([Ljava/lang/String;)V

u2(attributes_count)=0001

  [

    u2(attribute_name_index)= 0013= #19 = Utf8               Code

    u4(attribute_length)=00000036

    u2(max_stacks)=0002

    u2(max_locals)=0003

    u4(code_length)=00000012

      [

        bb 0008 new 0008

          #8 = Class              #36            //  BASE64Util

        59 dup

        b7 0009 invokespecial 0009 

           #9 = Methodref          #8.#28         //  BASE64Util."<init>":()V

        4c astore_1

        12 0a   ldc 0a

          #10 = String             #37            //  hello world

        4d astore_2

        2b aload_1 

        2c aload_2

        b6 000b invokevirtual 000b 

          #11 = Methodref          #8.#38         //  BASE64Util.encodeBase64:(Ljava/lang/String;)Ljava/lang/String;

        57 pop 

        b1 return 

      ]

  ]

u2(exception_table_length) =0000

u2(attribute_length)=0001

u2(attribute_name_index)=0014

   #20 = Utf8               LineNumberTable

u4(attribute_length)=00000012

u2(linenumber_lenth)=0004

  [

    (0000,0011)

    (0008,0012)

    (000b,0013)

    (0011,0014)

  ]

  public static void main(java.lang.String[]);
107  flags: ACC_PUBLIC, ACC_STATIC 108  Code: 109 stack=2, locals=3, args_size=1 110 0: new #8 // class BASE64Util 111 3: dup 112 4: invokespecial #9 // Method "<init>":()V 113 7: astore_1 114 8: ldc #10 // String hello world 115 10: astore_2 116 11: aload_1 117 12: aload_2 118 13: invokevirtual #11 // Method encodeBase64:(Ljava/lang/String;)Ljava/lang/String; 119 16: pop 120 17: return 121  LineNumberTable: 122 line 17: 0 123 line 18: 8 124 line 19: 11 125 line 20: 17 126 

 

13.4) 

 u2(access_flag)=0008=STATIC

u2(name_index)=0019=#25 = Utf8               <clinit>

u2(descriptor_index)=0012=#18 = Utf8               ()V

u2(attribute_coount)=0001

[

  u2(attribute_name_index)=0013=#19 = Utf8               Code

  u3(attribute_length)=000000025

  u2(max_stacks)=0001

  u2(max_locals)=0000

  u4(code_length)=0000000d

  [

    13 0008   ldc_w 0008 (將常量池中的項壓入棧)

      #8 = Class              #36            //  BASE64Util

    b6  000c    invokevirtual 000c

      #12 = Methodref          #39.#40        //  java/lang/Class.getName:()Ljava/lang/String;

    b8 000d   invokestatic 000d

      #13 = Methodref          #34.#41        //  java/util/logging/Logger.getLogger:(Ljava/lang/String;)Ljava/util/logging/Logger;

    b3 0006   putstatic 0006

       #6 = Fieldref           #8.#33         //  BASE64Util.log:Ljava/util/logging/Logger;

    b1 return

  ]

  u2(exception_table_length)=0000

  u2(attributes_count)=0001

  [

    u2(attribute_name_index)=0014

      #20 = Utf8               LineNumberTable

    u4(attribute_length)=0000 0006

    u2(line_number_table_length)=0001

    (0000,0007)

  ]

]

  static {};
128  flags: ACC_STATIC 129  Code: 130 stack=1, locals=0, args_size=0 131 0: ldc_w #8 // class BASE64Util 132 3: invokevirtual #12 // Method java/lang/Class.getName:()Ljava/lang/String; 133 6: invokestatic #13 // Method java/util/logging/Logger.getLogger:(Ljava/lang/String;)Ljava/util/logging/Logger; 134 9: putstatic #6 // Field log:Ljava/util/logging/Logger; 135 12: return 136  LineNumberTable: 137 line 7: 0

14)  

  u2(attribute_count) = 0001 

15) 

  u2(attribute_name_index)=001a=#26 = Utf8               SourceFile

  u4(attribute_length)=00000002

  u2(source_file_index)=001b=#27 = Utf8               BASE64Util.java

  SourceFile屬性

  SourceFile屬性是可選定長字段,位於ClassFile結構的屬性表。一個ClassFile結構中的屬性表最多只能包含一個SourceFile屬性。

  SourceFile屬性格式如下:

    

1 SourceFile_attribute {
2     u2 attribute_name_index;
3     u4 attribute_length;
4     u2 sourcefile_index;
5 }

SourceFile_attribute各項的說明如下:

  •   attribute_name_index:

  attribute_name_index 項的值必須是一個對常量池的有效索引。 常量池在該索引處的成員必須是 CONSTANT_Utf8_info結構,表示字符串“ SourceFile”。

  •   sourcefile_index

  sourcefile_index 項的值必須是一個對常量池的有效索引。 常量池在該索引處的成員必須是 CONSTANT_Utf8_info結構,表示一個字符串。

  sourcefile_index 項引用字符串表示被編譯的 Class 文件的源文件的名字。不包括源文件所在目錄的目錄名,也不包括源文件的絕對路徑名。
  平台相關(絕對路徑名等) 的附加信息必須是運行時解釋器( Runtime Interpreter)或開發工具在文件名實際使用時提供。





 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM