Java编译.class字节码图示解析

一、案例Java类结构

1.编写简单Java类上传到服务器JDK环境

我把它上传到了/data/javatest目录用于调试

public class PSVM {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

2.java命令编译PSVM类

javac PSVM.java

3.执行命令展示.class字节码 

od -t xC ./PSVM.class

上面就是打印出的PSVM.class的字节码文件了。

4.字节码规范

每个JDK实现厂商都需要遵守JVM规范进行字节码的生成,规范如下:

二、.class结构解析 

1.魔数、版本号、常量池元素个数(项数)

魔数cafebabe就不用提了

JDK版本16进制的34代表十进制52代表JDK8

常量池元素个数1d十进制是29,代表常量池有29项

 2.常量池字节占用的完整定义

3.解析项 

通过上面的定义规则,下图标记了一部分常量池项,每种连续的颜色代表一项

从第一项0a开始,CONSTANT_Methodref 0x0A 5 字节(1 + 2 + 2),所以第一行绿色5字节代表这个方法名常量,00 06代表指向第6项指向(第二行黑色框)00 0f表示索引是常量池15项(9行绿色)

4.对第1项的解析(0a 00 06 00 0f):

(1) 0a代表CONSTANT_Methodref是一个方法引用

(2) 00 06代表指向第6项指向(第二行黑色框)

第6项中07表示CONSTANT_Class常量名指向21项

第21项(最下面橙色):01 00 15 63 6f 6d 2f 73 6d 61 72 74 63 61 72 2f 6a 76 6d 2f 50 53 56 4d

01:类型标识符,表示 CONSTANT_Utf8 

00 15:长度,表示字符串有 21 个字节

从第四字节直到最后用ascii解析就是这个类:

(3) 00 0f指向常量池第15项

第15项: 0c 00 07 00 08

0c代表CONSTANT_NameAndType  (名称+类型)

00 07代表07项  01 00 06 3c 69 6e 69 74 3e ,01代表CONSTANT_Utf8 1+2+n,从第四位开始就是字符串信息:

3c 69 6e 69 74 3e正是构造方法<init>,说明这个第1项方法就是构造器

所以第一项0a 00 06 00 0f合在一起就是表示com/smartcar/jvm/PSVM<init>构造方法



其他项的向后以此类推即可

5.对第2项的解析(09 00 10 00 11):

(1) 09代表CONSTANT_Fieldref是一个成员字段引用

(2) 00 10代表指向第16项指向(第九行黄色框)07 00 17

07 00 17:  07代表CONSTANT_Class , 00 17代表第23项(最下面黄色)

第23项:01 00 10 6a 61 76 61 2f 6c 61 6e 67 2f 53 79 73 74 65 6d表示

(3)00 11代表0c 00 18 00 19(第九行红色)

00 18是第24项01 00 03 6f 75 74为out

所以第二项09 00 10 00 11合在一起就是java/lang/System  out对象

6.常量池全解析

  • 0a 00 06 00 0f

    • 方法引用:com/smartcar/jvm/PSVM.<init>()(构造器)。
  • 09 00 10 00 11

    • 字段引用:某字段,具体解析指向的类和字段描述符。
  • 08 00 12

    • 字符串常量:"Hello World"
  • 0a 00 13 00 14

    • 方法引用:某方法,具体需解析第 19 项(类)和 20 项(名称和描述符)。
  • 07 00 15

    • 类引用:com/smartcar/jvm/PSVM(类名)。
  • 07 00 16

    • 类引用:java/lang/Object(父类)。
  • 01 00 06 3c 69 6e 69 74 3e

    • UTF-8:<init>(构造方法名称)。
  • 01 00 03 28 29 56

    • UTF-8:() → 方法描述符,表示无参数、返回值为 void
  • 01 00 04 43 6f 64 65

    • UTF-8:Code(代码段属性名称)。
  • 01 00 0f 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65

    • UTF-8:LineNumberTable(行号表属性)。
  • 01 00 04 6d 61 69 6e

    • UTF-8:main(主方法名称)。
  • 01 00 16 28 5b 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b 29 56

    • UTF-8:([Ljava/lang/String;)Vmain 方法描述符。
  • 01 00 0a 53 6f 75 72 63 65 46 69 6c 65

    • UTF-8:SourceFile(源文件属性名称)。
  • 01 00 09 50 53 56 4d 2e 6a 61 76 61

    • UTF-8:PSVM.java(源文件名称)。
  • 0c 00 07 00 08

    • 名称和类型:<init>()V(构造方法的名称和描述符)。
  • 07 00 17

    • 类引用:java/io/PrintStream
  • 0c 00 18 00 19

    • 名称和类型:print(Ljava/lang/String;)Vprint 方法,参数为字符串,无返回值)。
  • 01 00 0b 48 65 6c 6c 6f 20 57 6f 72 6c 64

    • UTF-8:Hello World(字符串内容)。
  • 07 00 1a

    • 类引用:java/lang/System
  • 0c 00 1b 00 1c

    • 名称和类型:out Ljava/io/PrintStream;System.out 字段)。
  • 01 00 15 63 6f 6d 2f 73 6d 61 72 74 63 61 72 2f 6a 76 6d 2f 50 53 56 4d

    • UTF-8:com/smartcar/jvm/PSVM(类全限定名)。
  • 01 00 10 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74

    • UTF-8:java/lang/Object(父类全限定名)。
  • 01 00 10 6a 61 76 61 2f 6c 61 6e 67 2f 53 79 73 74 65 6d

    • UTF-8:java/lang/System
  • 01 00 03 6f 75 74

    • UTF-8:out(字段名称)。
  • 01 00 15 4c 6a 61 76 61 2f 69 6f 2f 50 72 69 6e 74 53 74 72 65 61 6d 3b

    • UTF-8:Ljava/io/PrintStream;(字段类型描述符)。
  • 01 00 13 6a 61 76 61 2f 69 6f 2f 50 72 69 6e 74 53 74 72 65 61 6d

    • UTF-8:java/io/PrintStream
  • 01 00 07 70 72 69 6e 74 6c 6e

    • UTF-8:println(方法名称)。
  • 01 00 15 28 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b 29 56

    • UTF-8:(Ljava/lang/String;)Vprintln 方法描述符。

7.访问修饰符

常量池之后开始就是声明信息,如访问修饰符等声明信息遵循下面的规则

访问修饰符计算规则

是个加法运算逻辑 21=0x0020+0x0001

ACC_PUBLIC 0x0001 声明为 public,可以从包外访问

ACC_SUPER 0x0020 在使用 invokespecial 指令调用父类方法时需要特殊处理

8.本类全限定名

访问修饰符下两位00 05在常量池第5项为

  • 07 00 15

    • 类引用:com/smartcar/jvm/PSVM(类名)

9.父类全限定名

  • 07 00 16

    • 类引用:java/lang/Object(父类)。

10.接口数

这个类没有实现接口,所以为0

11.成员变量

为了方便展示,我在java文件新加了两个成员变量用于观察成员变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

服务端相声演员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值