君临天下-Java

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
上一篇下一篇

猜你喜欢

热点阅读