JVM系列(2)——字节码

2 字节码

主要参考 《Java虚拟机规范(Java SE 8)》。

这部分简单做个了解,有个大概印象。

2.1 class 文件结构总览

虽说是 class 文件,但其实字节码可以存在于任何地方,并不局限于 class 文件。当然,一般为了描述方便,统称为 class 文件。

一个完整的 class 文件包括以下信息:

  • magic:魔数,4 字节,固定为 0xCAFEBABE,咖啡宝贝,呼应 Java 的咖啡 logo。没啥用,表示这是一个 class 文件。
  • minor_version:副版本号,2 字节。
  • major_version:主版本号,2 字节。和 minor_version 一起描述了 class 文件的版本号,JVM 可以根据这个版本号判断自己是否接受这个版本。
  • constant_pool_count:常量池计数器,2 字节。
  • constant_pool:常量池(表),变长。常量池记录信息的方式比较复杂,不同类型的常量有不同的数据结构,后面详述。
  • access_flags:访问标志,2 字节。
  • this_class:当前类在常量池表中的索引值,2 字节。
  • super_class:父类在常量池表中的索引值,2 字节。
  • interfaces_count:当前类实现的接口数量,2 字节。
  • interfaces:接口表,变长,长度根据实现接口的数量变化。
  • fields_count:字段数量,2 字节。
  • fields:字段表,类变量、实例变量都在这里,因为字段数量不定,所以也是变长。
  • methods_count:方法数量。
  • methods:方法表,当前类或接口中声明的所有方法,不含继承来的。
  • attributes_count:属性数量。
  • attributes:属性表,这里存储了一些扩展属性,会被字段表、方法表引用。

2.2 字节码反汇编

随便写个源文件:

package per.lvjc.jvm;

import java.util.function.Function;

public class ClassFileTest implements Function<Object, ClassFileTest> {
   

    private static volatile ClassFileTest instance = new ClassFileTest(4.4, 3);
    private final double d = 2.1;
    private int i = 1;

    public ClassFileTest(double d, int i) {
   
        this.i = i;
    }

    @Override
    public ClassFileTest apply(Object o) {
   
        if (o == null) {
   
            return null;
        }
        if (o instanceof ClassFileTest) {
   
            return (ClassFileTest) o;
        }
        return instance;
    }

    public static void main(String[] args) {
   
        ClassFileTest classFileTest = new ClassFileTest(1.1, 5);
        double x = classFileTest.d + classFileTest.i;
        System.out.println(x);
    }
}

编译成 class 文件,再执行 javap 命令:

javap -v -p ./target/classes/per/lvjc/jvm/ClassFileTest.class > ClassFileTest_javap.txt

输出了一个 200 多行的字节码反汇编文件。

2.2.1 基本信息
Classfile /D:/projects/personal/jvm/target/classes/per/lvjc/jvm/ClassFileTest.class
  Last modified 2021-3-24; size 1398 bytes
  MD5 checksum a8f7540c73cef1224dec4d3ccaf28ccc
  Compiled from "ClassFileTest.java"
public class per.lvjc.jvm.ClassFileTest extends java.lang.Object implements java.util.function.Function<java.lang.Object, per.lvjc.jvm.ClassFileTest>
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER

第一部分是一些基本信息,反汇编之后排版上应该经过了调整。this_class,super_class,access_flags 信息被提到前面来了。

这里,minor version 0,major version 52,也就是 52.0,具体是什么版本可以去官方查阅。

access_flag 有两个:

  • ACC_PUBLIC,因为这个类申明了 public;
  • ACC_SUPER,这个不用在意,Java 8 之后每个类都会有。
2.2.2 常量池
Constant pool:
   #1 = Methodref          #17.#50        // java/lang/Object."<init>":()V
   #2 = Double             2.1d
   #4 = Fieldref           #6.#51         // per/lvjc/jvm/ClassFileTest.d:D
   #5 = Fieldref           #6.#52         // per/lvjc/jvm/ClassFileTest.i:I
   #6 = Class              #53            // per/lvjc/jvm/ClassFileTest
   #7 = Fieldref           #6.#54         // per/lvjc/jvm/ClassFileTest.instance:Lper/lvjc/jvm/ClassFileTest;
   #8 = Double             1.1d
  #10 = Methodref          #6.#55         // per/lvjc/jvm/ClassFileTest."<init>":(DI)V
  #11 = Methodref          #17.#56        // java/lang/Object.getClass:()Ljava/lang/Class;
  #12 = Fieldref           #57.#58        // java/lang/System.out:Ljava/io/PrintStream;
  #13 = Methodref          #59.#60        // java/io/PrintStream.println:(D)V
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值