Java 中的子上下文在堆栈上是单独的行吗?
题
在Java中是这样的:
public void method() {
if (condition) {
Object x = ....;
}
System.out.println(x); // Error: x unavailable
}
我想知道的是:事实是 x
仅限于范围 if
-声明只是Java编译器的一个功能,或者是 x
实际上从堆栈中删除之后 if
-陈述?
解决方案
不,代码块不会获得单独的堆栈帧,而是使用周围的方法之一。
但是,一旦变量离开作用域,它在当前堆栈帧中的位置就可以重新用于其他变量。
栈帧的结构和使用在 Java 虚拟机规范§ 3.6 框架:
每次调用方法时都会创建一个新框架。当其方法调用完成时,框架将被销毁,无论该完成是正常完成还是突然完成(它会引发未捕获的异常)。
这明确指定了方法调用和框架之间的 1:1 关系。
其他提示
首先,在字节码中变量存储在变量时隙和可变的槽,而不是在堆栈。槽可以通过另一个变量被重新使用,但是它不保证该值将从可变时隙被删除。
例如,下面的类
public class A {
public void method(boolean condition) {
6 if (condition) {
7 Object x = "";
8 System.out.println(x);
9 }
10 System.out.println(condition);
}
}
被编译成字节码本:
// class version 50.0 (50)
public class A {
...
// access flags 0x1
public method(Z)V
L0
LINENUMBER 6 L0
ILOAD 1
IFEQ L1
L2
LINENUMBER 7 L2
LDC ""
ASTORE 2
L3
LINENUMBER 8 L3
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 2
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
L1
LINENUMBER 10 L1
FRAME SAME
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ILOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (Z)V
L4
LINENUMBER 11 L4
RETURN
L5
LOCALVARIABLE this LA; L0 L5 0
LOCALVARIABLE condition Z L0 L5 1
LOCALVARIABLE x Ljava/lang/Object; L3 L1 2
MAXSTACK = 2
MAXLOCALS = 3
}
请注意,在第7行X创建的变量被存入可变时隙2,它仍然是可用的在对应于第10行的字节码。
有是Java语言怎么也得被编译成字节码,然后其他几个例子,如何正确地编译一些语言结构不规范。但是Java编译器允许删除未使用的变量。例如。如果x被分配,而不是在任何地方使用,编译器允许下降代码。类似地,编译器是内联的所有静态常数。
是,它实际上从堆栈中移除使得先前由“X”可重复使用的一些其他本地变量占用的插槽。
不隶属于 StackOverflow