1、有类如下:
package jvm.loadingclass;
public class TestClass {
private int m;
public int inc() {
return m + 1;
}
}
2、编译之后:
- 0、1、2、3字节为魔数CAFEBABE;
- 4,5为次版本号,6,7为主版本号,0x34=52表示jdk1.8;
- 8、9字节0x16=22,表示有21个常量,索引范围为1-21,其中索引0较为特殊,用来达到“不指向常量池的任意一个常量”;
- A字节0x07,查“常量池的项目类型表”为CONSTANT_Class_info,其结构为下表,故而B、C字节为0x0002,指向第二个常量,内容为jvm/loadingclass/TestClass;
类型 | 名称 | 数量 |
---|---|---|
u1 | tag | 1 |
u2 | name_index | 1 |
- 0x0D字节为0x01001A6A…,查表知0x01对应CONSTANT_Class_info类型,查表得其结构如下表,由下表知: 其中0x01表示tag,0x001A为长度,是26,接着是26字节的用UTF-8缩略编码表示的字符串,为jvm/loadingclass/TestClass;
类型 | 名称 | 数量 |
---|---|---|
u1 | tag | 1 |
u2 | length | 1 |
u1 | bytes | length |
- UTF-8缩略编码:从‘\u0001’到‘\u007f’(相当于ASCII的1-127)用1个字节表示,从’\u0080’到‘\u07ff’用2个字节表示,从’\u0800’到’\uffff’用3个字节表示,具体的可以参照链接:UTF-8 可变编码格式,因为26个字母都在‘\u0001’到‘\u007f’之间,用一个字符表示,故而上图的“001A”对应26个字符jvm/loadingclass/TestClass,下图我加上一个中文“中”字,一个“中”需要3个字符表示,长度也随之变为“001D”,E4B8AD表示”中”字
- 0x5E字节: 0x0A0003000B Methodref_info(u1u2u2),指向3和11,得: java/lang/Object. < init>:()V
- 0x63字节:0x0C00070008 NameAndType(u1u2u2) 指向7.8:< init>得:()V
- 0xC1字节: 0x0900010013 Fieldref_info(u1u2u2),指向1和19得: jvm/loadingclass/TestClass.m:I
3、获得所有常量:
序号 位置 常量
1 0x0A 0x070002 类引用,指向第2个
2 0x0D 0x01001A6A… jvm/loadingclass/TestClass
3 0x2A 0x070004 类引用,指向第四个
4 0x2D 0x0100106A… java/lang/Object
5 0x40 0x0100016D m
6 0x44 0x01000149 I
7 0x48 0x010006… <init>
8 0x51 0x010003… ()V
9 0x57 0x010004 Code
10 0x5E 0x0A0003000B Methodref_info(u1u2u2),指向3和11:
java/lang/Object. <init>:()V
11 0x63 0x0C00070008 NameAndType(u1u2u2) 指向7.8:<init>:()V
12 0x68 0x01000F… LineNumberTable
13 0x7A 0x010012… LocalVariableTable
14 0x8f 0x010004… this
15 0x96 0x01001C… Ljvm/loadingclass/TestClass;
16 0xB5 0x010003… inc
17 0xBB 0x010003… ()I
18 0xC1 0x0900010013 Fieldref_info(u1u2u2),指向1和19:
jvm/loadingclass/TestClass.m:I
19 0xC6 0x0C00050006 NameAndType:m:I
20 0xCB 0x01000A… SourceFile
21 0xD8 0x01000E… TestClass.java
4、附录:
完整的编译后的文件(WinHex打开):
使用javap查看TestClass.class文件:
Classfile /F:/LAMP/MYWorkspaces/LearningJAVA/bin/jvm/loadingclass/TestClass.class
Last modified 2017-10-19; size 387 bytes
MD5 checksum df061cfaf6582f57693ebeb55c890962
Compiled from "TestClass.java"
public class jvm.loadingclass.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Class #2 // jvm/loadingclass/TestClass
#2 = Utf8 jvm/loadingclass/TestClass
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Utf8 m
#6 = Utf8 I
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Methodref #3.#11 // java/lang/Object."<init>":()V
#11 = NameAndType #7:#8 // "<init>":()V
#12 = Utf8 LineNumberTable
#13 = Utf8 LocalVariableTable
#14 = Utf8 this
#15 = Utf8 Ljvm/loadingclass/TestClass;
#16 = Utf8 inc
#17 = Utf8 ()I
#18 = Fieldref #1.#19 // jvm/loadingclass/TestClass.m:I
#19 = NameAndType #5:#6 // m:I
#20 = Utf8 SourceFile
#21 = Utf8 TestClass.java
{
public jvm.loadingclass.TestClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ljvm/loadingclass/TestClass;
public int inc();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: getfield #18 // Field m:I
4: iconst_1
5: iadd
6: ireturn
LineNumberTable:
line 6: 0
LocalVariableTable:
Start Length Slot Name Signature
0 7 0 this Ljvm/loadingclass/TestClass;
}
SourceFile: "TestClass.java"