ANATOMY / 原理实验室

字节码,如何成为运行。

从一份 .class,到每一条指令。让内存里的变化看得见。

HotSpot / JDK 17
真实 javap 字节码 · 可回放的语义模型
先分清两层方法区是 JVM 规范中的逻辑概念;本页展开 HotSpot 的具体位置。Metaspace、C/C++ malloc 堆、Code Cache、线程 OS 栈均属于本机侧管理范畴,彼此不等同。

从文件开始

加载阶段

—帧中 BCI
0Java 栈帧数
010203005040607

0 / 0
跳到关键事件 每次取指与执行分开显示

当前帧与调用链

线程私有

局部变量表 按槽位

操作数栈 左为底,右为顶

未赋值槽 ≠ null 对象引用。地址标签为示意;返回后销毁帧,不会自动销毁其引用的堆对象。

Java 堆对象

对象本体与引用

这里只显示示例相关对象。类加载器、JDK 基础类、解析引用数组等背景对象未按数量绘制;对象卡片不代表真实大小。

运行时常量池

VmDemo

数字是原始 class 文件的 # 索引。解释器内部缓存索引可能不同;Box 与 VmDemo 各有自己的池。

条目值 / 符号

Metaspace

C / C++ 堆与输入

Code Cache

.class 的每一部分,去了哪里。

规范语义与 HotSpot 17 的实现对应

输入部分本例去向进入后发生什么
magic / version / counts解析与格式检查用于构造结构;不作为 Java 指令执行,不必逐字节永久保留。
access_flags / this_class / super / interfacesInstanceKlass · 类身份与层次保存类修饰符、父类和接口关系。类的身份还包含定义它的加载器;本例 VmDemo 的父类是 java/lang/Object,无直接接口。
constant_pool:Integer / 数值Metaspace → 操作数栈如 #7=100000,ldc 复制 int 值;不是 new Integer,也不删除常量条目。
constant_pool:Class / Fieldref / MethodrefMetaspace + 解析缓存先是符号关系,按类加载器身份解析为类元数据、字段位置、调用目标等;不是全部装进 Java 堆。
CONSTANT_Utf8 / String 描述Symbol(native)/ String(Java 堆)名称/描述符可以符号化;字面量经解析取得驻留 String,其引用可被运行时缓存。两者不是同一种池。
fields:声明、类型、修饰符类元数据 / 布局HotSpot 静态值存储随 Class 镜像;实例值在 new 时分配于对象。默认值与 / 赋值分步展示。
methods + Code / max_stack / max_localsMethod / ConstMethod(Metaspace)保存指令与每次调用所需的帧上限;调用时才创建 locals/operand stack,字节码不复制到该帧。
LineNumberTable / LocalVariableTable / StackMapTable调试或验证元数据调试表可被压缩或省略;StackMapTable 用于验证,并非运行时栈。此直线程序没有该属性。
SourceFile / NestMembers / InnerClasses调试 / 类关系元数据本例的三个类级属性用于源文件信息、嵌套类关系和相关运行时检查;它们不作为运算值进入 Java 栈。
源码中的 static final 常量(补充)可能被编译器内联本示例没有 ConstantValue 字段。带 ConstantValue 的常量字段有专门初始化规则,不能一概认为都靠 的 putstatic 赋值。

这个演示的边界

主流程采用解释执行与按需解析的一种合法顺序。BCI、指令字节、常量池编号和帧上限来自实际 javac / javap;内存布局、读头移动和时间是教学示意,不是进程内存快照,也不预测真实机器的寄存器布局。

JVMS 把方法区逻辑上视为 heap 的一部分;图中“Java 堆”专指 HotSpot 的 GC 堆,Metaspace 不从这个 GC 堆分配。规范抽象层与实现层的同名词不能直接混用。

真实运行使用 OpenJDK 17.0.13,java -Xint -Xshare:off VmDemo 输出 100010。JIT 对照是独立概念动画,不声称此次单次调用触发了编译。未展开异常、线程并发、GC、类卸载、CDS 和所有对象头细节。

可核对的来源