在Java中不分配返回值的非无效方法调用

时间:2018-08-30 16:09:30

标签: java memory-management garbage-collection jvm

在没有返回值的接收者对象的情况下调用非空方法时,JVM会做什么? 它只是在找不到收件人的那一刻破坏了返回的对象?还是让返回的对象由垃圾收集器管理?或者是其他东西?。例如:

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

“您好,Java世界!”发生了什么?那退还了吗在什么时间被摧毁?

3 个答案:

答案 0 :(得分:1)

想象一下您点了饭。这顿饭装在一次性的盒子里。你拿出食物吃了。现在这些盒子对您来说毫无用处。您如何处理它们?丢弃它们。 Java GC也是如此。当没有通过任何对象引用或无法访问任何对象时,它将在下次触发gc时获得。看到这种情况的一种好方法是打开jvisualvm并继续跟踪String文字,然后启动gc。您会实时看到事情。

我希望这会有所帮助..!

答案 1 :(得分:1)

在这种情况下,返回值/引用将被简单地丢弃。可以将其视为立即超出范围的局部变量。

此外,由于没有实时引用,因此可以使用GC。因此,在将来的某个时候(不是马上),该对象将被GC化。

答案 2 :(得分: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终止时,将立即释放整个堆内存。