bilibili-深入理解JVM 虚拟机 学习笔记
The Java Virtual Machine Specification - Java SE 8 Edition
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
- 所有 .class 字节码文件的前
- 版本号
- 魔数之后的
4 个字节
(本机为:1.8.0) - minor version
- 次版本号(0)
0000
- major version
- 主版本号 (52 -> jdk1.8)
0034
- java -version
- 1.8.0_181
- 魔数之后的
- 常量池
- 版本号之后就是常量池的开始;
- 类中的很多信息都是由常量池来维护和描述的,
可以将常量池看作是Class文件的资源仓库
;- 类中的方法和变量信息
- 不是所有信息都是常量值
- 常量池主要存储两类常量
字面量
- 文本字符串
- final 声明的常量值
符号引用
- 类和接口全局限定名
- 字段的名称和描述符
- 方法的名称和描述符
- 总体结构:
- 常量池数量 (紧跟在版本号之后的
2个字节
)0018
0A00 --> 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;
- 解析常量池
- 0018
0A
00 --> 10 查询表1可知值为10的常量是CONSTANT_Methodref
- 下标0已由系统占用,此值索引值为 1
- 构成:index u2 + index u2
- 00180A
00 04
001409 --> 索引值 4 - 00180A00 04
0014
09 --> 索引值 20
- 040014
09
--> 9 查询表1CONSTANT_Fieldref
- 此值索引值为 2
- 构成:index u2 + index u2
0003
0015 --> 索引值 3- 0003
0015
--> 索引值 21
07
001607 --> 7 查询表1CONSTANT_Class
- 此值索引值为 3
- 构成:index u2
- 07
0016
07 --> 索引值 22
- 070016
07
--> 7 查询表1CONSTANT_Class
- 此值索引值为 4
- 构成:index u2
0017
0100 --> 索引值 23
- 0017
01
00 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 5
- 构成:length u2 + bytes u1
- 001701
00 01
610100 --> 长度值 1 ,接下来的u1 * length
为具体值 - 00170100 01
61
0100 --> 97 查询ASCII码表 ‘a’
- 0161
01
00 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 6
- 构成:length u2 + bytes u1
- 016101
00 01
490100 --> 长度值 1 - 01
49
0100 --> 73 查询ASCII码表 ‘I’
- 0149
01
00 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 7
- 构成:length u2 + bytes u1
- 014901
00 06
3C696E --> 长度值 6 - 06
3C696E 69743E
01 --> 60 105 110 105 116 62 查询ASCII码表 ‘’
- 69743E
01
--> 1 查询表1CONSTANT_utf8
- 此值索引值为 8
- 构成:length u2 + bytes u1
0003
2829 --> 长度值 3- 0003
2829 56
010004 --> 40 41 86 查询ASCII码表 ‘()V’
- 56
01
0004 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 9
- 构成:length u2 + bytes u1
- 5601
0004
--> 长度值 4 436F6465
--> 67 111 100 101 查询ASCII码表 ‘Code’
01
000F4C --> 1 查询表1CONSTANT_utf8
- 此值索引值为 10
- 构成:length u2 + bytes u1
- 01
000F
4C --> 长度值 15 - 01000F
4C 696E654E 756D6265 72546162 6C65
0100 --> 76 105 110 101 78 117 109 98 101 114 84 97 98 108 101 查询ASCII码表 ‘LineNumberTable’
- 6C65
01
00 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 11
- 构成:length u2 + bytes u1
- 6C6501
00 12
4C6F63 --> 长度值 18 - 12
4C6F63 616C5661 72696162 6C655461 626C65
01 --> 76 111 99 97 108 86 97 114 105 97 98 108 101 84 97 98 108 101 查询ASCII码表 ‘LocalVariableTable’
- 626C65
01
--> 1 查询表1CONSTANT_utf8
- 此值索引值为 12
- 构成:length u2 + bytes u1
0004
7468 --> 长度值 4- 0004
7468 6973
0100 --> 116 104 105 115 查询ASCII码表 ‘this’
- 6973
01
00 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 13
- 构成:length u2 + bytes u1
- 697301
00 1D
4C6E65 --> 长度值 xxx - 1D
4C6E65 775F7061 636B6167 652F6A76 6D2F7033 372F4D79 54657374 313B
0100 --> 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;’
- 313B
01
00 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 14
- 构成:length u2 + bytes u1
- 313B01
00 04
676574 --> 长度值 4 - 04
676574 41
010003 --> 103 101 116 65 查询ASCII码表 ‘getA’
- 41
01
0003 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 15
- 构成:length u2 + bytes u1
- 4101
0003
--> 长度值 3 282949
01 --> 40 41 73 查询ASCII码表 ‘()I’
- 282949
01
--> 1 查询表1CONSTANT_utf8
- 此值索引值为 16
- 构成:length u2 + bytes u1
0004
7365 --> 长度值 4- 0004
7365 7441
0100 --> 115 101 116 65 查询ASCII码表 ‘setA’
- 7441
01
00 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 17
- 构成:length u2 + bytes u1
- 744101
00 04
284929 --> 长度值 4 - 04
284929 56
01000A --> 40 73 41 86 查询ASCII码表 ‘(I)V’
- 56
01
000A --> 1 查询表1CONSTANT_utf8
- 此值索引值为 18
- 构成:length u2 + bytes u1
- 5601
000A
--> 长度值 10 536F7572 63654669 6C65
0100 --> 83 111 117 114 99 101 70 105 108 101 查询ASCII码表 ‘SourceFile’
- 6C65
01
00 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 19
- 构成:length u2 + bytes u1
- 6C6501
00 0C
4D7954 --> 长度值 12 - 0C
4D7954 65737431 2E6A6176 61
0C0007–> 77 121 84 101 115 116 49 46 106 97 118 97 查询ASCII码表 ‘MyTest1.java’
- 61
0C
0007 --> 12 查询表1CONSTANT_NameAndType
- 此值索引值为 20
- 构成 u2 name_index; u2 descriptor_index;
- name_index 610C
0007
--> 指向索引 7 - descriptor_index
0008
0C00 --> 指向索引 8
- 0008
0C
00 --> 12 查询表1CONSTANT_NameAndType
- 此值索引值为 21
- 构成 u2 name_index; u2 descriptor_index;
- name_index 00080C
00 05
000601 --> 指向索引 5 - descriptor_index 00080C00 05
0006
01 --> 指向索引 6
- 050006
01
--> 1 查询表1 -->CONSTANT_utf8
- 此值索引值为 22
- 构成:length u2 + bytes u1
- length
001B
6E65 --> 长度值 27 - 001B
6E65 775F7061 636B6167 652F6A76 6D2F7033 372F4D79 54657374 31
010010 --> 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’
- 31
01
0010 --> 1 查询表1CONSTANT_utf8
- 此值索引值为 23
- 构成:length u2 + bytes u1
- 3101
0010
--> 长度值 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’
- 0018
- 常量池之后是 access_flags u2
0021
0003 --> 查询 Table 4.1-A 可得- 0x0021 = 0x0020 | 0x0020 (逻辑或)
- 即此类的访问描述符有 : ACC_SUPER ACC_PUBLIC
- 之后是 this_class u2
- 0021
0003
--> 指向常量池索引值 3 - 即 new_package/jvm/p37/MyTest1
- 0021
- 之后是 super_class u2
0004
0000 --> 指向常量池索引值 4- java/lang/Object
- 之后是 interfaces_count u2
- 0004
0000
--> 即实现接口数量为0
- 0004
- 之后是 interfaces[interfaces_count] u2;
- 由于 interfaces_count 为 0,所以此项不存在
- 之后是 fields_count u2
0001
0002 --> 即 1个字段属性
- 之后是 fields[fields_count] field_info
- field_info[0]
- access_flags u2
- 0001
0002
--> 查询 Table 4.5-A --> = 0x0002 --> ACC_PRIVATE
- 0001
- name_index u2
0005
0006 --> 指向常量池索引 5 --> a
- descriptor_index u2
- 0005
0006
--> 指向常量池索引 6 --> I
- 0005
- attributes_count u2
0000
0003 --> 0 个 attribute_info
- attributes[attributes_count] attribute_info
- access_flags u2
- field_info[0]
- 之后是 methods_count u2
- 0000
0003
--> 即有3个方法
- 0000
- 之后是 methods[methods_count] method_info
- method_info[0]
- access_flags u2
0001
0007 --> 查询 Table 4.6-A --> = 0x0001 --> ACC_PUBLIC
- name_index u2
- 0001
0007
--> 指向常量池索引 7 --> --> 表示此方法为构造方法
- 0001
- descriptor_index u2
0008
0001 --> 指向常量池索引 8 --> ()V --> () 内无参数表示此构造方法为无参构造器
- attributes_count u2
- 0008
0001
--> 1 个 attribute_info
- 0008
- attributes[attributes_count] attribute_info
- attributes[0]
- attribute_name_index u2
0009
0000 --> 指向常量池索引 9 --> Code
- attribute_length u4
- 0009
0000 0038
0002 --> 长度 56
- 0009
- info[attribute_length] u1
- 长度 * u1
- 0038
0002 00010000 000A2AB7 00012A04 B50002B1 00000002 000A0000 000A0002 00000003 00040005 000B0000 000C0001 0000000A 000C000D 0000
0001 --> ???
- attribute_name_index u2
- attributes[0]
- access_flags u2
- method_info[1]
- access_flags u2
- 0000
0001
--> 查询 Table 4.6-A --> = 0x0001 --> ACC_PUBLIC
- 0000
- name_index u2
000E
000F --> 指向常量池索引 14 --> getA --> 方法名
- descriptor_index u2
- 000E
000F
--> 指向常量池索引 15 --> ()I --> 方法描述符
- 000E
- attributes_count u2
0001
0009 --> 1 个 attribute_info
- attributes[attributes_count] attribute_info
- attributes[0]
- attribute_name_index u2
- 0001
0009
--> 指向常量池索引 9 --> Code
- 0001
- attribute_length u4
0000002F
--> 长度 47
- info[attribute_length] u1
- 长度 * u1
00010001 00000005 2AB40002 AC000000 02000A00 00000600 01000000 08000B00 00000C00 01000000 05000C00 0D0000
00 --> ???
- attribute_name_index u2
- attributes[0]
- access_flags u2
- method_info[2]
- access_flags u2
- 0D0000
00 01
001000 --> ACC_PUBLIC
- 0D0000
- name_index u2
- 01
0010
00 --> 16 -->
- 01
- descriptor_index u2
- 010010
00 11
000100 --> 17 -->
- 010010
- attributes_count u2
- 11
0001
00 --> 1 个
- 11
- attributes[attributes_count] attribute_info
- attributes[0]
- attribute_name_index u2
- 110001
00 09
000000 --> 指向常量池索引 9 --> Code
- 110001
- attribute_length u4
- 09
000000 3E
000200 --> 长度 62
- 09
- info[attribute_length] u1
- 长度 * u1
- 3E
000200 02000000 062A1BB5 0002B100 00000200 0A000000 0A000200 00000C00 05000D00 0B000000 16000200 00000600 0C000D00 00000000 06000500 060001
00 --> ???
- attribute_name_index u2
- attributes[0]
- access_flags u2
- method_info[0]
- 之后是 attributes_count u2
- 060001
00 01
001200 --> 1个
- 060001
- 之后是 attributes[attributes_count] attribute_info
- attributes[0]
- attribute_name_index u2
- 01
0012
00 --> 指向常量池索引 18 -->SourceFile
- 01
- attribute_length u4
- 010012
00 000002
00 13 --> 长度 2
- 010012
- info[attribute_length] u1
- 000002
00 13
--> 指向索引 19 --> MyTest1.java
- 000002
- attribute_name_index u2
- attributes[0]
前要知识:
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 Name | Value | Interpretation |
---|---|---|
ACC_PUBLIC | 0x0001 | Declared public; may be accessed from outside its package. |
ACC_FINAL | 0x0010 | Declared final; no subclasses allowed. |
ACC_SUPER | 0x0020 | Treat superclass methods specially when invoked by the invokespecial instruction. |
ACC_INTERFACE | 0x0200 | Is an interface, not a class. |
ACC_ABSTRACT | 0x0400 | Declared abstract; must not be instantiated. |
ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |
ACC_ANNOTATION | 0x2000 | Declared as an annotation type. |
ACC_ENUM | 0x4000 | Declared as an enum type. |
表2 : 4.3.2. Field Descriptors
Table 4.3-A. Interpretation of field descriptors
FieldType term | Type | Interpretation |
---|---|---|
B | byte | signed byte |
C | char | Unicode character code point in the Basic Multilingual Plane, encoded with UTF-16 |
D | double | double-precision floating-point value |
F | float | single-precision floating-point value |
I | int | integer |
J | long | long integer |
L ClassName ; | reference | an instance of class ClassName |
S | short | signed short |
Z | boolean | true or false |
[ | reference | one array dimension |
V | Void | void type |
例如:
L 对象类型(全限定名);(如:String
记录为 Ljava/lang/String;
)
[ 数组类型 (如:int[]
记录为 [I
、String[][]
记录为 [[java/lang/String;
、以此类推)
表3 : 4.4. The Constant Pool
cp_info {
u1 tag;
u1 info[];
}
Constant Type | Value |
---|---|
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 |
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 Name | Value | Interpretation |
---|---|---|
ACC_PUBLIC | 0x0001 | Declared public; may be accessed from outside its package. |
ACC_PRIVATE | 0x0002 | Declared private; usable only within the defining class. |
ACC_PROTECTED | 0x0004 | Declared protected; may be accessed within subclasses. |
ACC_STATIC | 0x0008 | Declared static. |
ACC_FINAL | 0x0010 | Declared final; never directly assigned to after object construction (JLS §17.5). |
ACC_VOLATILE | 0x0040 | Declared volatile; cannot be cached. |
ACC_TRANSIENT | 0x0080 | Declared transient; not written or read by a persistent object manager. |
ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |
ACC_ENUM | 0x4000 | Declared 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 Name | Value | Interpretation |
---|---|---|
ACC_PUBLIC | 0x0001 | Declared public; may be accessed from outside its package. |
ACC_PRIVATE | 0x0002 | Declared private; accessible only within the defining class. |
ACC_PROTECTED | 0x0004 | Declared protected; may be accessed within subclasses. |
ACC_STATIC | 0x0008 | Declared static. |
ACC_FINAL | 0x0010 | Declared final; must not be overridden (§5.4.5). |
ACC_SYNCHRONIZED | 0x0020 | Declared synchronized; invocation is wrapped by a monitor use. |
ACC_BRIDGE | 0x0040 | A bridge method, generated by the compiler. |
ACC_VARARGS | 0x0080 | Declared with variable number of arguments. |
ACC_NATIVE | 0x0100 | Declared native; implemented in a language other than Java. |
ACC_ABSTRACT | 0x0400 | Declared abstract; no implementation is provided. |
ACC_STRICT | 0x0800 | Declared strictfp; floating-point mode is FP-strict. |
ACC_SYNTHETIC | 0x1000 | Declared 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种数据结构(此表为总结型资料,可由以上几个官方资料汇聚可得)