JVM学习笔记11 - Java字节码初识

bilibili-深入理解JVM 虚拟机 学习笔记
The Java Virtual Machine Specification - Java SE 8 Edition

JVM学习笔记 10 类加载器总结

P37_Java字节码文件结构剖析(37)

Java 之所以跨平台是因为 JVM 不是跨平台的;java 编译器在任何平台(Linux、Unix、Macx、Windows)编译后的字节码文件其实是一样的,只是字节码在不同 OS 平台的 JVM上 解释执行不同而已,JVM 屏蔽了底层的细节。

字节码规范属于 java 虚拟机规范的一部分;

javap -c xxx 对代码进行反汇


package new_package.jvm.p37;

public class MyTest1 {

    private int a = 1;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
}

javap -verbose new_package.jvm.p37.MyTest1
javap -verbose xxx 输出附加信息(包括:魔数、版本号、常量池、类信息、类的构造方法、类中的方法信息、类变量、成员变量等)

Classfile /opensource/gitee/java-read-sources-sample/target/classes/new_package/jvm/p37/MyTest1.class
  Last modified 2020-5-2; size 485 bytes
  MD5 checksum 6ddfedbb5912c36dba00bb4712b7118f
  Compiled from "MyTest1.java"
public class new_package.jvm.p37.MyTest1
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#20         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#21         // new_package/jvm/p37/MyTest1.a:I
   #3 = Class              #22            // new_package/jvm/p37/MyTest1
   #4 = Class              #23            // java/lang/Object
   #5 = Utf8               a
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lnew_package/jvm/p37/MyTest1;
  #14 = Utf8               getA
  #15 = Utf8               ()I
  #16 = Utf8               setA
  #17 = Utf8               (I)V
  #18 = Utf8               SourceFile
  #19 = Utf8               MyTest1.java
  #20 = NameAndType        #7:#8          // "<init>":()V
  #21 = NameAndType        #5:#6          // a:I
  #22 = Utf8               new_package/jvm/p37/MyTest1
  #23 = Utf8               java/lang/Object
{
  public new_package.jvm.p37.MyTest1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_1
         6: putfield      #2                  // Field a:I
         9: return
      LineNumberTable:
        line 3: 0
        line 5: 4
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   Lnew_package/jvm/p37/MyTest1;

  public int getA();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field a:I
         4: ireturn
      LineNumberTable:
        line 8: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lnew_package/jvm/p37/MyTest1;

  public void setA(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 a:I
         5: return
      LineNumberTable:
        line 12: 0
        line 13: 5
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   Lnew_package/jvm/p37/MyTest1;
            0       6     1     a   I
}
SourceFile: "MyTest1.java"

字节码文件解析

使用 Hex Fiend 软件打开 MyTest1.class 文件:

CAFEBABE 00000034 00180A00 04001409 00030015 07001607 00170100 01610100 
01490100 063C696E 69743E01 00032829 56010004 436F6465 01000F4C 696E654E 
756D6265 72546162 6C650100 124C6F63 616C5661 72696162 6C655461 626C6501 
00047468 69730100 1D4C6E65 775F7061 636B6167 652F6A76 6D2F7033 372F4D79 
54657374 313B0100 04676574 41010003 28294901 00047365 74410100 04284929 
5601000A 536F7572 63654669 6C650100 0C4D7954 65737431 2E6A6176 610C0007 
00080C00 05000601 001B6E65 775F7061 636B6167 652F6A76 6D2F7033 372F4D79 
54657374 31010010 6A617661 2F6C616E 672F4F62 6A656374 00210003 00040000 
00010002 00050006 00000003 00010007 00080001 00090000 00380002 00010000 
000A2AB7 00012A04 B50002B1 00000002 000A0000 000A0002 00000003 00040005 
000B0000 000C0001 0000000A 000C000D 00000001 000E000F 00010009 0000002F 
00010001 00000005 2AB40002 AC000000 02000A00 00000600 01000000 08000B00 
00000C00 01000000 05000C00 0D000000 01001000 11000100 09000000 3E000200 
02000000 062A1BB5 0002B100 00000200 0A000000 0A000200 00000C00 05000D00 
0B000000 16000200 00000600 0C000D00 00000000 06000500 06000100 01001200 
00000200 13
  • 魔数
    • 所有 .class 字节码文件的前4个字节都是魔数,魔数值为固定值:0xCAFEBABE
  • 版本号
    • 魔数之后的 4 个字节 (本机为:1.8.0)
    • minor version
      • 次版本号(0)
      • 0000
    • major version
      • 主版本号 (52 -> jdk1.8)
      • 0034
    • java -version
      • 1.8.0_181
  • 常量池
    • 版本号之后就是常量池的开始;
    • 类中的很多信息都是由常量池来维护和描述的,可以将常量池看作是Class文件的资源仓库
      • 类中的方法和变量信息
      • 不是所有信息都是常量值
    • 常量池主要存储两类常量
      • 字面量
        • 文本字符串
        • final 声明的常量值
      • 符号引用
        • 类和接口全局限定名
        • 字段的名称和描述符
        • 方法的名称和描述符
    • 总体结构:
      • 常量池数量 (紧跟在版本号之后的2个字节
        • 00180A00 --> 24-1=23 (注意:0x0000 下标0保留)
        • 常量池数组中元素的个数 = 常量池数 - 1
        • 某些常量池索引值的数据在特定情况下需要表达「不引用任何一个常量池」的含义,使用下标0表示;
        • 索引为0是一个特殊常量(保留常量),只不过它不位于常量表中,这个常量对应 null 值;
      • 常量池数组 (紧跟在常量池数量之后, )
        • 常量池数组中的不同元素类型和结构都是不同的
        • 但是,每一个元素的第一个数据都是一个u1类型,该字节是个标志位
          • u1 类型,占据一个字节( 官方资料:The types u1, u2, and u4 represent an unsigned one-, two-, or four-byte quantity, respectively. )
          • JVM 解析常量池时,根据这个 u1 类型的值来获取元素的具体类型
    • 用描述符描述方法时,按照先参数列表,后返回值的顺序描述,参数列表按照参数的严格顺序放在一组()之内;
      • 如:String getNameByIdAndStuNo(Long id,String stuNo)
      • (J,Ljava/lang/String;)Ljava/lang/String;
    • 解析常量池
      • 00180A00 --> 10 查询表1可知值为10的常量是 CONSTANT_Methodref
        • 下标0已由系统占用,此值索引值为 1
        • 构成:index u2 + index u2
        • 00180A00 04001409 --> 索引值 4
        • 00180A00 04001409 --> 索引值 20
      • 04001409 --> 9 查询表1 CONSTANT_Fieldref
        • 此值索引值为 2
        • 构成:index u2 + index u2
        • 00030015 --> 索引值 3
        • 00030015 --> 索引值 21
      • 07001607 --> 7 查询表1 CONSTANT_Class
        • 此值索引值为 3
        • 构成:index u2
        • 07001607 --> 索引值 22
      • 07001607 --> 7 查询表1 CONSTANT_Class
        • 此值索引值为 4
        • 构成:index u2
        • 00170100 --> 索引值 23
      • 00170100 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 5
        • 构成:length u2 + bytes u1
        • 00170100 01610100 --> 长度值 1 ,接下来的 u1 * length 为具体值
        • 00170100 01610100 --> 97 查询ASCII码表 ‘a’
      • 01610100 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 6
        • 构成:length u2 + bytes u1
        • 01610100 01490100 --> 长度值 1
        • 01490100 --> 73 查询ASCII码表 ‘I’
      • 01490100 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 7
        • 构成:length u2 + bytes u1
        • 01490100 063C696E --> 长度值 6
        • 063C696E 69743E01 --> 60 105 110 105 116 62 查询ASCII码表 ‘’
      • 69743E01 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 8
        • 构成:length u2 + bytes u1
        • 00032829 --> 长度值 3
        • 00032829 56010004 --> 40 41 86 查询ASCII码表 ‘()V’
      • 56010004 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 9
        • 构成:length u2 + bytes u1
        • 56010004 --> 长度值 4
        • 436F6465 --> 67 111 100 101 查询ASCII码表 ‘Code’
      • 01000F4C --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 10
        • 构成:length u2 + bytes u1
        • 01000F4C --> 长度值 15
        • 01000F4C 696E654E 756D6265 72546162 6C650100 --> 76 105 110 101 78 117 109 98 101 114 84 97 98 108 101 查询ASCII码表 ‘LineNumberTable’
      • 6C650100 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 11
        • 构成:length u2 + bytes u1
        • 6C650100 124C6F63 --> 长度值 18
        • 124C6F63 616C5661 72696162 6C655461 626C6501 --> 76 111 99 97 108 86 97 114 105 97 98 108 101 84 97 98 108 101 查询ASCII码表 ‘LocalVariableTable’
      • 626C6501 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 12
        • 构成:length u2 + bytes u1
        • 00047468 --> 长度值 4
        • 00047468 69730100 --> 116 104 105 115 查询ASCII码表 ‘this’
      • 69730100 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 13
        • 构成:length u2 + bytes u1
        • 69730100 1D4C6E65 --> 长度值 xxx
        • 1D4C6E65 775F7061 636B6167 652F6A76 6D2F7033 372F4D79 54657374 313B0100 --> 76 110 101 119 95 112 97 99 107 97 103 101 47 106 118 109 47 112 51 55 47 77 121 84 101 115 116 49 59 查询ASCII码表 ‘Lnew_package/jvm/p37/MyTest1;’
      • 313B0100 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 14
        • 构成:length u2 + bytes u1
        • 313B0100 04676574 --> 长度值 4
        • 04676574 41010003 --> 103 101 116 65 查询ASCII码表 ‘getA’
      • 41010003 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 15
        • 构成:length u2 + bytes u1
        • 41010003 --> 长度值 3
        • 28294901 --> 40 41 73 查询ASCII码表 ‘()I’
      • 28294901 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 16
        • 构成:length u2 + bytes u1
        • 00047365 --> 长度值 4
        • 00047365 74410100 --> 115 101 116 65 查询ASCII码表 ‘setA’
      • 74410100 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 17
        • 构成:length u2 + bytes u1
        • 74410100 04284929 --> 长度值 4
        • 04284929 5601000A --> 40 73 41 86 查询ASCII码表 ‘(I)V’
      • 5601000A --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 18
        • 构成:length u2 + bytes u1
        • 5601000A --> 长度值 10
        • 536F7572 63654669 6C650100 --> 83 111 117 114 99 101 70 105 108 101 查询ASCII码表 ‘SourceFile’
      • 6C650100 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 19
        • 构成:length u2 + bytes u1
        • 6C650100 0C4D7954 --> 长度值 12
        • 0C4D7954 65737431 2E6A6176 610C0007–> 77 121 84 101 115 116 49 46 106 97 118 97 查询ASCII码表 ‘MyTest1.java’
      • 610C0007 --> 12 查询表1 CONSTANT_NameAndType
        • 此值索引值为 20
        • 构成 u2 name_index; u2 descriptor_index;
        • name_index 610C0007 --> 指向索引 7
        • descriptor_index 00080C00 --> 指向索引 8
      • 00080C00 --> 12 查询表1 CONSTANT_NameAndType
        • 此值索引值为 21
        • 构成 u2 name_index; u2 descriptor_index;
        • name_index 00080C00 05000601 --> 指向索引 5
        • descriptor_index 00080C00 05000601 --> 指向索引 6
      • 05000601 --> 1 查询表1 --> CONSTANT_utf8
        • 此值索引值为 22
        • 构成:length u2 + bytes u1
        • length 001B6E65 --> 长度值 27
        • 001B6E65 775F7061 636B6167 652F6A76 6D2F7033 372F4D79 54657374 31010010 --> 110 101 119 95 112 97 99 107 97 103 101 47 106 118 109 47 112 51 55 47 77 121 84 101 115 116 49 查询ASCII码表 --> ‘new_package/jvm/p37/MyTest1’
      • 31010010 --> 1 查询表1 CONSTANT_utf8
        • 此值索引值为 23
        • 构成:length u2 + bytes u1
        • 31010010 --> 长度值 16
        • 6A617661 2F6C616E 672F4F62 6A656374 --> 106 97 118 97 47 108 97 110 103 47 79 98 106 101 99 116 查询ASCII码表 --> ‘java/lang/Object’
    • 常量池之后是 access_flags u2
      • 00210003 --> 查询 Table 4.1-A 可得
      • 0x0021 = 0x0020 | 0x0020 (逻辑或)
      • 即此类的访问描述符有 : ACC_SUPER ACC_PUBLIC
    • 之后是 this_class u2
      • 00210003 --> 指向常量池索引值 3
      • 即 new_package/jvm/p37/MyTest1
    • 之后是 super_class u2
      • 00040000 --> 指向常量池索引值 4
      • java/lang/Object
    • 之后是 interfaces_count u2
      • 00040000 --> 即实现接口数量为0
    • 之后是 interfaces[interfaces_count] u2;
      • 由于 interfaces_count 为 0,所以此项不存在
    • 之后是 fields_count u2
      • 00010002 --> 即 1个字段属性
    • 之后是 fields[fields_count] field_info
      • field_info[0]
        • access_flags u2
          • 00010002 --> 查询 Table 4.5-A --> = 0x0002 --> ACC_PRIVATE
        • name_index u2
          • 00050006 --> 指向常量池索引 5 --> a
        • descriptor_index u2
          • 00050006 --> 指向常量池索引 6 --> I
        • attributes_count u2
          • 00000003 --> 0 个 attribute_info
        • attributes[attributes_count] attribute_info
    • 之后是 methods_count u2
      • 00000003 --> 即有3个方法
    • 之后是 methods[methods_count] method_info
      • method_info[0]
        • access_flags u2
          • 00010007 --> 查询 Table 4.6-A --> = 0x0001 --> ACC_PUBLIC
        • name_index u2
          • 00010007 --> 指向常量池索引 7 --> --> 表示此方法为构造方法
        • descriptor_index u2
          • 00080001 --> 指向常量池索引 8 --> ()V --> () 内无参数表示此构造方法为无参构造器
        • attributes_count u2
          • 00080001 --> 1 个 attribute_info
        • attributes[attributes_count] attribute_info
          • attributes[0]
            • attribute_name_index u2
              • 00090000 --> 指向常量池索引 9 --> Code
            • attribute_length u4
              • 00090000 00380002 --> 长度 56
            • info[attribute_length] u1
              • 长度 * u1
              • 00380002 00010000 000A2AB7 00012A04 B50002B1 00000002 000A0000 000A0002 00000003 00040005 000B0000 000C0001 0000000A 000C000D 00000001 --> ???
      • method_info[1]
        • access_flags u2
          • 00000001 --> 查询 Table 4.6-A --> = 0x0001 --> ACC_PUBLIC
        • name_index u2
          • 000E000F --> 指向常量池索引 14 --> getA --> 方法名
        • descriptor_index u2
          • 000E000F --> 指向常量池索引 15 --> ()I --> 方法描述符
        • attributes_count u2
          • 00010009 --> 1 个 attribute_info
        • attributes[attributes_count] attribute_info
          • attributes[0]
            • attribute_name_index u2
              • 00010009 --> 指向常量池索引 9 --> Code
            • attribute_length u4
              • 0000002F --> 长度 47
            • info[attribute_length] u1
              • 长度 * u1
              • 00010001 00000005 2AB40002 AC000000 02000A00 00000600 01000000 08000B00 00000C00 01000000 05000C00 0D000000 --> ???
      • method_info[2]
        • access_flags u2
          • 0D000000 01001000 --> ACC_PUBLIC
        • name_index u2
          • 01001000 --> 16 -->
        • descriptor_index u2
          • 01001000 11000100 --> 17 -->
        • attributes_count u2
          • 11000100 --> 1 个
        • attributes[attributes_count] attribute_info
          • attributes[0]
            • attribute_name_index u2
              • 11000100 09000000 --> 指向常量池索引 9 --> Code
            • attribute_length u4
              • 09000000 3E000200 --> 长度 62
            • info[attribute_length] u1
              • 长度 * u1
              • 3E000200 02000000 062A1BB5 0002B100 00000200 0A000000 0A000200 00000C00 05000D00 0B000000 16000200 00000600 0C000D00 00000000 06000500 06000100 --> ???
    • 之后是 attributes_count u2
      • 06000100 01001200 --> 1个
    • 之后是 attributes[attributes_count] attribute_info
      • attributes[0]
        • attribute_name_index u2
          • 01001200 --> 指向常量池索引 18 --> SourceFile
        • attribute_length u4
          • 01001200 00000200 13 --> 长度 2
        • info[attribute_length] u1
          • 00000200 13 --> 指向索引 19 --> MyTest1.java



前要知识:

The types u1, u2, and u4 represent an unsigned one-, two-, or four-byte quantity, respectively.

表1 : 4.1. The ClassFile Structure
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];
}

ClassFile access_flags --> Table 4.1-A. Class access and property modifiers

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
ACC_FINAL0x0010Declared final; no subclasses allowed.
ACC_SUPER0x0020Treat superclass methods specially when invoked by the invokespecial instruction.
ACC_INTERFACE0x0200Is an interface, not a class.
ACC_ABSTRACT0x0400Declared abstract; must not be instantiated.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
ACC_ANNOTATION0x2000Declared as an annotation type.
ACC_ENUM0x4000Declared as an enum type.
表2 : 4.3.2. Field Descriptors

Table 4.3-A. Interpretation of field descriptors

FieldType termTypeInterpretation
Bbytesigned byte
CcharUnicode character code point in the Basic Multilingual Plane, encoded with UTF-16
Ddoubledouble-precision floating-point value
Ffloatsingle-precision floating-point value
Iintinteger
Jlonglong integer
L ClassName ;referencean instance of class ClassName
Sshortsigned short
Zbooleantrue or false
[referenceone array dimension
VVoidvoid type

例如:

L 对象类型(全限定名);(如:String 记录为 Ljava/lang/String;
[ 数组类型 (如:int[] 记录为 [IString[][] 记录为 [[java/lang/String;、以此类推)

表3 : 4.4. The Constant Pool
cp_info {
    u1 tag;
    u1 info[];
}
Constant TypeValue
CONSTANT_Class7
CONSTANT_Fieldref9
CONSTANT_Methodref10
CONSTANT_InterfaceMethodref11
CONSTANT_String8
CONSTANT_Integer3
CONSTANT_Float4
CONSTANT_Long5
CONSTANT_Double6
CONSTANT_NameAndType12
CONSTANT_Utf81
CONSTANT_MethodHandle15
CONSTANT_MethodType16
CONSTANT_InvokeDynamic18

CONSTANT_Class_info {
    u1 tag;
    u2 name_index;
}

CONSTANT_Fieldref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}

CONSTANT_Methodref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}

CONSTANT_InterfaceMethodref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}

CONSTANT_String_info {
    u1 tag;
    u2 string_index;
}

CONSTANT_Integer_info {
    u1 tag;
    u4 bytes;
}

CONSTANT_Float_info {
    u1 tag;
    u4 bytes;
}

CONSTANT_Long_info {
    u1 tag;
    u4 high_bytes;
    u4 low_bytes;
}

CONSTANT_Double_info {
    u1 tag;
    u4 high_bytes;
    u4 low_bytes;
}

CONSTANT_NameAndType_info {
    u1 tag;
    u2 name_index;
    u2 descriptor_index;
}

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}
表4 : 4.5. Fields
field_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}

field_info access_flags --> Table 4.5-A. Field access and property flags

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
ACC_PRIVATE0x0002Declared private; usable only within the defining class.
ACC_PROTECTED0x0004Declared protected; may be accessed within subclasses.
ACC_STATIC0x0008Declared static.
ACC_FINAL0x0010Declared final; never directly assigned to after object construction (JLS §17.5).
ACC_VOLATILE0x0040Declared volatile; cannot be cached.
ACC_TRANSIENT0x0080Declared transient; not written or read by a persistent object manager.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
ACC_ENUM0x4000Declared as an element of an enum.
表5 : 4.6. Methods
method_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

method_info access_flags --> Table 4.6-A. Method access and property flags

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
ACC_PRIVATE0x0002Declared private; accessible only within the defining class.
ACC_PROTECTED0x0004Declared protected; may be accessed within subclasses.
ACC_STATIC0x0008Declared static.
ACC_FINAL0x0010Declared final; must not be overridden (§5.4.5).
ACC_SYNCHRONIZED0x0020Declared synchronized; invocation is wrapped by a monitor use.
ACC_BRIDGE0x0040A bridge method, generated by the compiler.
ACC_VARARGS0x0080Declared with variable number of arguments.
ACC_NATIVE0x0100Declared native; implemented in a language other than Java.
ACC_ABSTRACT0x0400Declared abstract; no implementation is provided.
ACC_STRICT0x0800Declared strictfp; floating-point mode is FP-strict.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
表6 : 4.7. Attributes
attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}
表7 : 4.7.3. The Code Attribute
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];
}


表10:Class 文件结构中常量池中的11种数据结构(此表为总结型资料,可由以上几个官方资料汇聚可得)
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值