• 欢迎访问本站,本站记录博主日常编程遇到的问题,知识,惊奇软件等。如有问题还请留言


    Deprecated: strip_tags(): Passing null to parameter #1 ($string) of type string is deprecated in /www/wwwroot/gschaos.club/wp-content/themes/Git-alpha-6h0SRk/header.php on line 294

局部变量表中槽的问题

java mysticalycc 2天前 19次浏览 已收录 0个评论
文章目录[隐藏]

jvm的槽为啥是32位,64jvm也是32位呢

1. 什么是 jvm 的“槽”(slot)

  • 在 java 虚拟机中,局部变量表(Local Variable Table) 是方法栈帧的一部分。
  • 它由一组 slot(位) 组成,每个 slot 的基本单位是 32 位(4字节)
  • slot 可以存放:
    • int, float, reference, returnAddress 等单类型。
    • long, double 需要占用两个连续的 slot(低位 + 高位)。

2. 为什么 slot 统一为 32 位

这是 jvm 设计规范(java 虚拟机规范,jvmS) 的要求,背后主要有几个考虑:

  1. 规范一致性(平台无关)
    jvm 的设计目标是“一次编译,到处运行”。
    如果 slot 大小随 CPU 架构变化(32 位机器用 4 字节,64 位机器用 8 字节),那么字节码在不同平台上的局部变量表布局就不一致了,跨平台运行性就破坏了。

  2. 操作码设计简化
    jvm 指令集的很多操作(iload, istore 等)都默认按 32 位为单位 来操作。
    如果 slot 大小不固定,就需要一堆复杂的变长逻辑,指令集也会变臃肿。

  3. 兼容 64 位数据类型
    jvm 规范规定:longdouble 类型占用两个 slot(2 × 32 = 64 位)。
    这样不管底层是 32 位 CPU 还是 64 位 CPU,字节码都能有一致的表示方法。

    👉 所以局部变量表不是 CPU 原生寄存器的直接映射,而是 jvm 抽象出的统一数据模型。


3. 那么在 64 位 jvm 中会怎样?

  • 局部变量表依然是以 32 位 slot 为基本单位,不会因为 64 位机器而变成 64 位。
  • 但在 实现层面,JVM 内部可能用 64 位寄存器来装这些数据(因为现代 CPU 就是 64 位寄存器架构)。只是逻辑上仍然按“32 位单位 + long/double 占两个 slot”来解释。
  • reference 类型(对象引用)来说,在 64 位 JVM 上,它确实是 64 位指针,但 JVM 会把它拆成“占两个 slot”,或者在实现上做优化(比如启用 压缩指针 compressed oops,用 32 位表示对象引用)。

4. 总结

  • jvm 规范固定了 slot = 32 位,这是一个 平台无关的抽象层设计
  • longdouble 用两个 slot 来存储,保证了 64 位数据的表示能力。
  • 在 64 位 JVM 上,slot 概念仍是 32 位的,但实现可以用更宽的寄存器来承载数据,并通过压缩指针等优化减少空间浪费。

局部变量表(slot)的深度在编译期已经固定,而对象引用在 64 位 JVM 下却可能是 64 位宽度,怎么对齐?是不是要占 2 个槽?

1. 编译期:引用类型永远视为单槽

  • java 编译器(javac)在编译 .java.class 时,生成的 局部变量表位数按照 jvm 规范来的
  • 在 jvm 规范里:
    • int/float/reference/returnAddress占 1 个 slot
    • long/double占 2 个 slot

👉 所以在编译时,不管你未来运行在 32 位还是 64 位 JVM,字节码里的 reference 类型始终是

例如:

Object o = new Object();

在字节码里,它对应的局部变量就是 1 个 slot,绝不会占 2 个。


2. 运行期:64 位 jvm 如何放下 64 位指针

这里涉及到 实现层的抽象与优化

  • 如果开启压缩指针(默认在 64 位 JVM 且堆 < 32G 时开启)
    • 引用是 32 位(4字节),直接装进 1 个 slot,和规范完全一致。
  • 如果关闭压缩指针(或者堆内存非常大,需要 64 位指针)
    • 引用在物理上是 64 位(8字节),但 JVM 内部仍然抽象成“逻辑上的一个 slot”。
    • HotSpot 的做法是:局部变量表在实现层面是一个 Slot[] 数组,每个元素大小足够容纳 64 位(通常是 intptr_t),所以即使 reference 是 64 位,也依然放得下。

👉 这就是为什么 你看到的局部变量表深度在编译期是固定的

  • 规范层面:引用始终是 1 槽
  • 实现层面:JVM 的 slot 单元实际大小 >= 4 字节,能存下 64 位指针
  • 因此不会出现“编译期分配 1 ,运行期却要用 2 槽”的矛盾

3. 为什么 long/double 要占 2 个槽,而 reference 不要?

这是设计上的差异:

  • longdouble真正的 64 位数值类型,字节码规范明确规定它们要占 2 个槽(并且涉及到 lload/ldc2_w 等专门指令)。
  • reference抽象的引用类型,jvm 规范只要求它能存放一个“对象引用”,至于底层是 32 位还是 64 位,是 JVM 实现细节。

所以:

  • long/double编译期和运行期都固定占 2 槽
  • reference规范上始终 1 槽,实际存储宽度由 JVM 内部实现决定

4. 总结

  • 你看到的“局部变量表槽的深度固定”,是因为 编译器就按规范生成,和平台无关。
  • 在 64 位 JVM 上,如果不开启压缩指针:
    • 引用在物理上是 64 位
    • 但 JVM 内部的 slot 实现足够大(一般是 64 位宽度),所以依然占 1 个 slot,而不是 2 个。

👉 结论:引用类型永远是 1 槽,和压缩指针是否开启无关;差别只在于槽内部存的东西是 32 位还是 64 位。


MysticalYcc , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:局部变量表中槽的问题
喜欢 (0)
mysticalycc
关于作者:
简短的个人签名

Warning: Attempt to read property "comment_author_email" on null in /www/wwwroot/gschaos.club/wp-content/themes/Git-alpha-6h0SRk/comments.php on line 47
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到