Java class文件
2020-04-13 本文已影响0人
老荀
class文件结构
假设我这里有这样一个java文件, 结构非常简单
// Hello.java
public class Hello extends Father implements World {
private volatile static int age = 8;
public transient double score = 87.33D;
protected String name = "xunjunjie";
public String hasReturn(Integer age, Long number) {
return "abc";
}
public void noReturn(List<String> names) {
}
@Override
public String print() {
return this.name;
}
}
// Father.java
public abstract class Father {
}
// World.java
public interface World {
String print();
}
用Hex Friend工具打开
image.png
magic
4个字节
CAFEBABE
minor_version
2个字节
0000
major_version
2个字节,16进制34=十进制52
版本对应表:
J2SE 8 = 52
J2SE 7 = 51
J2SE 6.0 = 50
J2SE 5.0 = 49
JDK 1.4 = 48
JDK 1.3 = 47
JDK 1.2 = 46
JDK 1.1 = 45
0034
constant_pool_count
2个字节,十进制50
表明有49个常量,预留了一个空位代表不在常量池中
0032
javap查看常量池
$ javap -v Hello
Constant pool:
#1 = Methodref #10.#41 // jvmtest/Father."<init>":()V
#2 = Double 87.33d
#4 = Fieldref #9.#42 // jvmtest/Hello.score:D
#5 = String #43 // xunjunjie
#6 = Fieldref #9.#44 // jvmtest/Hello.name:Ljava/lang/String;
#7 = String #45 // abc
#8 = Fieldref #9.#46 // jvmtest/Hello.age:I
#9 = Class #47 // jvmtest/Hello
#10 = Class #48 // jvmtest/Father
#11 = Class #49 // jvmtest/World
#12 = Utf8 age
#13 = Utf8 I
#14 = Utf8 score
#15 = Utf8 D
#16 = Utf8 name
#17 = Utf8 Ljava/lang/String;
#18 = Utf8 <init>
#19 = Utf8 ()V
#20 = Utf8 Code
#21 = Utf8 LineNumberTable
#22 = Utf8 LocalVariableTable
#23 = Utf8 this
#24 = Utf8 Ljvmtest/Hello;
#25 = Utf8 hasReturn
#26 = Utf8 (Ljava/lang/Integer;Ljava/lang/Long;)Ljava/lang/String;
#27 = Utf8 Ljava/lang/Integer;
#28 = Utf8 number
#29 = Utf8 Ljava/lang/Long;
#30 = Utf8 noReturn
#31 = Utf8 (Ljava/util/List;)V
#32 = Utf8 names
#33 = Utf8 Ljava/util/List;
#34 = Utf8 LocalVariableTypeTable
#35 = Utf8 Ljava/util/List<Ljava/lang/String;>;
#36 = Utf8 Signature
#37 = Utf8 (Ljava/util/List<Ljava/lang/String;>;)V
#38 = Utf8 <clinit>
#39 = Utf8 SourceFile
#40 = Utf8 Hello.java
#41 = NameAndType #18:#19 // "<init>":()V
#42 = NameAndType #14:#15 // score:D
#43 = Utf8 xunjunjie
#44 = NameAndType #16:#17 // name:Ljava/lang/String;
#45 = Utf8 abc
#46 = NameAndType #12:#13 // age:I
#47 = Utf8 jvmtest/Hello
#48 = Utf8 jvmtest/Father
#49 = Utf8 jvmtest/World
常量池
常量池中的常量都由2个部分组成,一个部分是tag,另一个部分由常量的类型决定
Utf8
常量类型 | 项目 | 字节长度 | 描述 |
---|---|---|---|
CONSTANT_Utf8_info | tag | u1 | 01 |
CONSTANT_Utf8_info | length | u2 | 字符串的长度 |
CONSTANT_Utf8_info | bytes | u1 | 每一个字节代表一个字符 |
举例:
#43 = Utf8 xunjunjie
# In HexFriend
01000978756E6A756E6A6965
# 整理
# utf8 长度9
01 0009 78 75 6E 6A 75 6E 6A 69 65
78 75 6E 6A 75 6E 6A 69 65
# 通过查询ASCII
x u n j u n j i e
Integer
常量类型 | 项目 | 字节长度 | 描述 |
---|---|---|---|
CONSTANT_Utf8_info | tag | u1 | 01 |
CONSTANT_Utf8_info | bytes | u4 | Integer4个字节 |
String
常量类型 | 项目 | 字节长度 | 描述 |
---|---|---|---|
CONSTANT_String_info | tag | u1 | 08 |
CONSTANT_String_info | index | u2 | 对应utf8字面值的索引 |
举例:
#5 = String #43 // xunjunjie
# In HexFriend
08002B
# 整理
# String 43
08 002B
Double
常量类型 | 项目 | 字节长度 | 描述 |
---|---|---|---|
CONSTANT_Double_info | tag | u1 | 06 |
CONSTANT_Double_info | bytes | u8 | 高位在前存储的double值 |
举例:
#2 = Double 87.33d
# In HexFriend
064055D51EB851EB85
# 整理
# Double
06 4055D51EB851EB85
Long l = 0x4055D51EB851EB85L;
// 100000001010101110101010001111010111000010100011110101110000101
System.out.println(Long.toBinaryString(l));
// 87.33
System.out.println(Double.longBitsToDouble(l));
Class
常量类型 | 项目 | 字节长度 | 描述 |
---|---|---|---|
CONSTANT_Class_info | tag | u1 | 07 |
CONSTANT_Class_info | index | u2 | 指向全类名的utf8索引 |
举例:
#9 = Class #47 // jvmtest/Hello
# In HexFriend
07002F
# 整理
# Class 47
07 002F
Methodref
常量类型 | 项目 | 字节长度 | 描述 |
---|---|---|---|
CONSTANT_Methodref_info | tag | u1 | 10(0A) |
CONSTANT_Methodref_info | index | u2 | 归属类CONSTANT_Class_info的索引 |
CONSTANT_Methodref_info | index | u2 | CONSTANT_NameAndType_info索引 |
举例:
#1 = Methodref #10.#41 // jvmtest/Father."<init>":()V
# In HexFriend
0A000A0029
# 整理
# Methodref 10 41
0A 000A 0029
NameAndType
常量类型 | 项目 | 字节长度 | 描述 |
---|---|---|---|
CONSTANT_NameAndType_info | tag | u1 | 12(0C) |
CONSTANT_NameAndType_info | index | u2 | 字段或者方法名常量项的索引 |
CONSTANT_NameAndType_info | index | u2 | 字段或者方法名描述符索引 |
举例:
#42 = NameAndType #14:#15 // score:D
# In HexFriend
0C000E000F
# 整理
# NameAndType 14 15
0C 000E 000F
Fieldref
常量类型 | 项目 | 字节长度 | 描述 |
---|---|---|---|
CONSTANT_Fieldref_info | tag | u1 | 09 |
CONSTANT_Fieldref_info | index | u2 | 归属类CONSTANT_Class_info的索引 |
CONSTANT_Fieldref_info | index | u2 | CONSTANT_NameAndType_info索引 |
举例:
#8 = Fieldref #9.#46 // jvmtest/Hello.age:I
# In HexFriend
090009002E
# 整理
# Fieldref 09 46
09 0009 002E