Java 中的子上下文在堆栈上是单独的行吗?

发布于 2024-09-05 21:19:36 字数 285 浏览 6 评论 0原文

在Java中是这样的:

public void method() {
  if (condition) {
    Object x = ....;
  }
  System.out.println(x); // Error: x unavailable
}

我想知道的是:事实上x仅限于if语句的范围只是Java的一个功能编译器,或者在 if 语句之后实际上从堆栈中删除了 x 吗?

In Java this is the case:

public void method() {
  if (condition) {
    Object x = ....;
  }
  System.out.println(x); // Error: x unavailable
}

What I'm wondering is this: Is the fact that x is limited to the scope of the if-statement just a feature of the Java compiler, or is x actually removed from the stack after the if-statement?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心欲静而疯不止 2024-09-12 21:19:36

不,代码块不会获得单独的堆栈帧,而是使用周围的方法之一。

但是,一旦变量离开作用域,它在当前堆栈帧中的位置就可以重新用于其他变量。

堆栈帧的结构和使用在 Java 虚拟机规范§ 3.6 框架

每次调用方法时都会创建一个新框架。当方法调用完成时,框架就会被销毁,无论该完成是正常完成还是突然完成(它会抛出未捕获的异常)。

这明确指定了方法调用和框架之间的 1:1 关系。

No, code blocks don't get a separate stack frame, the use the one of the surrounding method.

However, once a variable leaves scope, it's place in the current stack frame can be re-used for other variables.

The structure and use of a stack frame is described in the Java Virtual Machine Specification § 3.6 Frames:

A new frame is created each time a method is invoked. A frame is destroyed when its method invocation completes, whether that completion is normal or abrupt (it throws an uncaught exception).

This definitely specifies a 1:1 relation between method invocations and frames.

扶醉桌前 2024-09-12 21:19:36

块是 Java 语言的一部分(这是一种结构化编程语言)虽然它们不是已编译字节码的一部分(这是一个非-结构化语言)。

类文件中的方法规范指定该方法总共使用多少个局部变量,位于实际指令列表之上。但是Java代码中的块一旦出现在哪里,就无法从字节码中推断出来。

Blocks are a part of the Java language (which is a structured programming language) while they are not a part of the compiled bytecode (which is an non-structured language).

A method specification in a class file specifies how many local variables the method uses in total, above the actual list of instructions. But where the blocks once where in the Java code can not be inferred from the bytecode.

行至春深 2024-09-12 21:19:36

首先,在字节码中,变量存储在变量槽和变量槽中,而不是存储在堆栈中。该槽可以被另一个变量重用,但不能保证值会从变量槽中删除。

例如,以下类

  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 已被分配,但未在任何地方使用,则允许编译器删除该代码。同样,编译器正在内联所有静态常量。

First of all, in the bytecode variables are stored in the variable slots and variable slots and not on the stack. The slot could be reused by another variable, but it is not guaranteed that value would be removed from the variable slot.

For example, the following class

  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);
    }
  }

is compiled into this bytecode:

// 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
}

Note that variable x created at line 7 is stored into the variable slot 2, which is still available at the bytecode corresponding to line 10.

There is no specification on how Java language have to be compiled into the bytecode other then few examples how to properly compile some language constructs. However Java compiler is allowed to eliminate unused variables. E.g. if x were assigned, but not used anywhere, compiler is allowed to drop that code. Similarly, compiler is inlining all the static constants.

心房的律动 2024-09-12 21:19:36

是的,它确实从堆栈中删除,使得之前被“x”占用的槽可以被其他局部变量重用。

Yes, it is really removed from the stack making the slot previously occupied by 'x' reusable by some other local variable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文