了解 aload_0 和 iload_0 的工作原理

Understanding how aload_0 and iload_0 work

我正在学习更多关于如何阅读 Java 字节码的知识,这非常有趣。据我了解,每个堆栈框架都有自己的变量数组。那么,所有类型(int 或引用)是否共享同一个数组?

public class ByteTest {
    private int thisField;

    public ByteTest(int f){
        thisField = f;
    }
}

在这段代码中,iload_1表示0th处已经有一个值,但是f显然是第一个int 此代码块中的变量,除了 this 是此堆栈中的第一个 reference 变量。那么,所有类型都共享同一个数组吗?我的推理正确吗?这是构造函数的字节码

/* L4 */
0 aload_0;                /* this */
1 invokespecial 10;       /* java.lang.Object() */
/* L5 */
4 aload_0;                /* this */
5 iload_1;                /* f */
6 putfield 13;            /* .thisField */
/* L6 */
9 return;

是的,你是对的。堆栈框架为所有类型共享一组局部变量。另请参阅 JVM 规范中的 this section

Each frame (§2.6) contains an array of variables known as its local variables. The length of the local variable array of a frame is determined at compile-time and supplied in the binary representation of a class or interface along with the code for the method associated with the frame (§4.7.3).

A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress. A pair of local variables can hold a value of type long or double.

是的,所有类型共享同一个数组。最好的理解方式是你有一个最多包含 65535 个槽的数组,你可以在其中存储你想要的任何变量(尽管 long 和 double 各占用两个槽)。您甚至可以在方法的不同部分将多种不同类型的值存储在同一个槽中。当加载 class 时,JVM 会对字节码进行静态分析,以确保加载的值始终与最初存储的类型相同。

所以下面是有效的

iconst_0
istore_0
iload_0
aconst_null
astore_0
aload_0

但以下无效

iconst_0
istore_0
aload_0

请注意,Java 字节码也是如此。 Dalvik 字节码具有相似但不同的类型检查规则。例如,Dalvik 中的常量是无类型的,移动指令也是如此,因此与第二个示例等效的 Dalvik 将通过验证。