Java中不指定返回值的非void方法调用

Java中不指定返回值的非void方法调用,java,memory-management,garbage-collection,jvm,Java,Memory Management,Garbage Collection,Jvm,当调用非void方法时,如果返回值没有收件人对象,JVM会做什么? 它只是在找不到收件人的瞬间销毁返回的对象?还是将返回的对象留给垃圾收集器管理?还是别的什么?。例如: public class PrincipalClass { public static void main(String[] args) { returnStringMethod(); } public static String returnStringMethod() {

当调用非void方法时,如果返回值没有收件人对象,JVM会做什么? 它只是在找不到收件人的瞬间销毁返回的对象?还是将返回的对象留给垃圾收集器管理?还是别的什么?。例如:

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

返回的“Hello,Java world!”会发生什么情况?什么时候被毁?

想象一下你点了一顿饭。这顿饭是装在一次性盒子里的。你把食物拿出来吃了。现在这些盒子对你没用了。你用它们做什么。。?丢弃它们。JavaGC也是如此。当任何对象未通过任何对象引用或不可访问时,它将在下次触发gc时获取。看到这一点的一个好方法是打开jvisualvm并继续跟踪字符串文字,然后启动gc。你可以实时看到事情


我希望这有帮助

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


此外,由于没有对此的实时引用,因此它有资格使用GC。因此,在将来的某个时候(不是马上),对象将被GCed。

当您编译程序时,例如使用
javac
并运行命令
javap-c PrincipalClass
javap
是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
}
从“PrincipalClass.java”编译而来
公共类主类{
公共主类();
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
公共静态void main(java.lang.String[]);
代码:
0:invokestatic#2//Method returnStringMethod:()Ljava/lang/String;
3:流行音乐
4:返回
公共静态java.lang.String returnStringMethod();
代码:
0:ldc#3//String你好,Java世界!
2:轮到你了
}
关键部分是方法
main
,它由字节码指令
invokestatic
pop
return
组成

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

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

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


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

这个问题可能已经有了答案:没有Java方法返回对象,尽管其中许多方法返回对对象的引用。如果忽略这样一个引用,那么它将丢失。作为一个完全独立的问题,VM中没有活动引用的对象有资格进行垃圾收集。考虑到对同一对象可以有多个引用,在这种通用性级别上,被忽略的方法的返回值和它可能引用的任何对象的处置之间没有特殊的联系。为了使事情更加混乱,这可能被放入字符串池中,因此不会被垃圾收集。是的,这是一种特殊情况。但一般来说,这就是处理对象的方式。哦,好吧,我不知道OpenJVisualVM,谢谢你的额外建议@Rajansinghing这对AOT编译器来说也是一个潜在的简单优化