Non void方法调用而不在Java中分配返回值

问题描述 投票:2回答:3

在没有返回值的收件人对象的情况下调用非void方法时,JVM是什么?它只是在没有找到收件人的那一刻销毁返回的对象?或者它使返回的对象与垃圾收集器一起管理?或者是其他东西?。例如:

public class PrincipalClass {
    public static void main(String[] args) {
        returnStringMethod();
    }
    public static String returnStringMethod() {
        return "Hello, Java world!";
    }
}

“你好,Java世界!”会发生什么?那是归来的?什么时候被摧毁?

java memory-management garbage-collection jvm
3个回答
1
投票

想象一下,你点了一顿饭。这顿饭来自一次性盒子。你把食物取出来吃了。现在这些盒子对你来说没用。你用它们做什么..?丢弃它们。 Java GC也是如此。当任何对象未通过任何对象引用或无法接近时,它将在下次触发gc时触发。看到这个的一个好方法是打开jvisualvm并继续跟踪字符串文字,然后激活gc。你会实时看到的东西。

我希望这有帮助..!


1
投票

在这种情况下,简单地丢弃返回的值/引用。可以把它想象成一个立即超出范围的局部变量。

此外,由于没有对此的实时引用,因此它符合GC的条件。因此,在未来的某个时刻(不是马上),对象将被GCed。


1
投票

编译程序时,例如使用javac并运行命令javap -c PrincipalClassjavap是JDK附带的命令),您将看到以下输出:

Compiled from "PrincipalClass.java"
public class PrincipalClass {
  public PrincipalClass();
    Code:
       0: aload_0
       1: invokespecial #1                // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #2                // Method returnStringMethod:()Ljava/lang/String;
       3: pop
       4: return

  public static java.lang.String returnStringMethod();
    Code:
       0: ldc           #3                // String Hello, Java world!
       2: areturn
}

关键部分是方法main由字节码指令invokestaticpopreturn组成。

invokestatic指令将调用方法returnStringMethod并在操作数堆栈上保留对String的引用。随后的pop指令将删除最顶层的堆栈条目,即引用。在该指令之后,没有引用当前方法中的字符串。因此,如果它不是从代码中引用的字符串文字,那么它有资格进行垃圾收集。具体来说,它与ldc中的returnStringMethod()指令相关联。

原则上,这里不需要pop指令,因为return指令将破坏当前方法的整个堆栈帧,包括其操作数堆栈。

在任何一种情况下,答案都是垃圾收集器,它可能会在以后发现没有对该对象的引用。这至少是它正式运作的方式。 JVM中还有一个优化器,可以检测方法是否忽略在被调用方法中直接创建的对象并优化此特定代码。但是,结果更像是从不首先创建对象,而不是在之后立即销毁它。而且这个优化器只查看与性能相关的代码。

另一点是,对于您的简单程序,垃圾收集器可能永远不会运行,因为在这短暂的执行时间内不需要它。当JVM终止时,将立即释放整个堆内存。

© www.soinside.com 2019 - 2024. All rights reserved.