当前帧与调用链
线程私有局部变量表 按槽位
操作数栈 左为底,右为顶
未赋值槽 ≠ null 对象引用。地址标签为示意;返回后销毁帧,不会自动销毁其引用的堆对象。
从一份 .class,到每一条指令。让内存里的变化看得见。
加载阶段
未赋值槽 ≠ null 对象引用。地址标签为示意;返回后销毁帧,不会自动销毁其引用的堆对象。
这里只显示示例相关对象。类加载器、JDK 基础类、解析引用数组等背景对象未按数量绘制;对象卡片不代表真实大小。
数字是原始 class 文件的 # 索引。解释器内部缓存索引可能不同;Box 与 VmDemo 各有自己的池。
| 条目 | 值 / 符号 |
|---|
规范语义与 HotSpot 17 的实现对应
| 输入部分 | 本例去向 | 进入后发生什么 |
|---|---|---|
| magic / version / counts | 解析与格式检查 | 用于构造结构;不作为 Java 指令执行,不必逐字节永久保留。 |
| access_flags / this_class / super / interfaces | InstanceKlass · 类身份与层次 | 保存类修饰符、父类和接口关系。类的身份还包含定义它的加载器;本例 VmDemo 的父类是 java/lang/Object,无直接接口。 |
| constant_pool:Integer / 数值 | Metaspace → 操作数栈 | 如 #7=100000,ldc 复制 int 值;不是 new Integer,也不删除常量条目。 |
| constant_pool:Class / Fieldref / Methodref | Metaspace + 解析缓存 | 先是符号关系,按类加载器身份解析为类元数据、字段位置、调用目标等;不是全部装进 Java 堆。 |
| CONSTANT_Utf8 / String 描述 | Symbol(native)/ String(Java 堆) | 名称/描述符可以符号化;字面量经解析取得驻留 String,其引用可被运行时缓存。两者不是同一种池。 |
| fields:声明、类型、修饰符 | 类元数据 / 布局 | HotSpot 静态值存储随 Class 镜像;实例值在 new 时分配于对象。默认值与 |
| methods + Code / max_stack / max_locals | Method / ConstMethod(Metaspace) | 保存指令与每次调用所需的帧上限;调用时才创建 locals/operand stack,字节码不复制到该帧。 |
| LineNumberTable / LocalVariableTable / StackMapTable | 调试或验证元数据 | 调试表可被压缩或省略;StackMapTable 用于验证,并非运行时栈。此直线程序没有该属性。 |
| SourceFile / NestMembers / InnerClasses | 调试 / 类关系元数据 | 本例的三个类级属性用于源文件信息、嵌套类关系和相关运行时检查;它们不作为运算值进入 Java 栈。 |
| 源码中的 static final 常量(补充) | 可能被编译器内联 | 本示例没有 ConstantValue 字段。带 ConstantValue 的常量字段有专门初始化规则,不能一概认为都靠 |
主流程采用解释执行与按需解析的一种合法顺序。BCI、指令字节、常量池编号和帧上限来自实际 javac / javap;内存布局、读头移动和时间是教学示意,不是进程内存快照,也不预测真实机器的寄存器布局。
JVMS 把方法区逻辑上视为 heap 的一部分;图中“Java 堆”专指 HotSpot 的 GC 堆,Metaspace 不从这个 GC 堆分配。规范抽象层与实现层的同名词不能直接混用。
真实运行使用 OpenJDK 17.0.13,java -Xint -Xshare:off VmDemo 输出 100010。JIT 对照是独立概念动画,不声称此次单次调用触发了编译。未展开异常、线程并发、GC、类卸载、CDS 和所有对象头细节。