Non void Метод, вызываемый без присваивания возвращаемого значения в Java - PullRequest
0 голосов
/ 30 августа 2018

Что делает JVM при вызове не пустого метода без объекта-получателя для возвращаемого значения? Это просто уничтожить возвращенный объект в тот момент, когда не найдет получателя? или он возвращает возвращаемый объект для управления с помощью сборщика мусора? Или что-то другое?. Например:

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

Что происходит с "Привет, мир Java!" что было возвращено? В какое время уничтожено?

Ответы [ 3 ]

0 голосов
/ 30 августа 2018

В этом случае возвращаемое значение / ссылка просто отбрасывается. Думайте об этом как о локальной переменной, которая сразу выходит из области видимости.

Кроме того, поскольку нет прямых ссылок на это, он получает право на GC. Следовательно, в какой-то момент в будущем (не сразу) объект будет GCed.

0 голосов
/ 30 августа 2018

Когда вы компилируете свою программу, например, используя 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
}

Важной частью является метод main, состоящий из инструкций байт-кода invokestatic, pop, return.

Инструкция invokestatic вызовет метод returnStringMethod и оставит ссылку на String в стеке операндов. Следующая инструкция pop удалит самую верхнюю запись стека, то есть ссылку. После этой инструкции нет ссылки на строку из текущего метода. Таким образом, он имел право на сборку мусора, если он не был строковым литералом, на который ссылались из кода. В частности, он связывается с инструкцией ldc внутри returnStringMethod().

В принципе, инструкция pop здесь не обязательна, так как инструкция return уничтожит весь кадр стека текущего метода, включая его стек операндов.

В любом случае ответ заключается в том, что он зависит от сборщика мусора, который может позже обнаружить, что нет ссылок на объект. По крайней мере, так работает формально. В JVM также есть оптимизатор, который может определять, игнорирует ли метод объект, созданный непосредственно в вызываемом методе, и оптимизировать этот конкретный код. Тем не менее, результат больше похож на то, что вы никогда не создаете объект, а не уничтожаете его сразу после. И этот оптимизатор смотрит только на код, который оказался важным для производительности.

Другой момент заключается в том, что для вашей простой программы сборщик мусора, скорее всего, никогда не будет работать, так как он не нужен в это короткое время выполнения. Вся память кучи будет освобождена сразу после завершения работы JVM.

0 голосов
/ 30 августа 2018

Представь, что ты заказал еду. Еда пришла в одноразовых коробках. Вы достали еду, съели ее. Теперь ящики для вас бесполезны. Что вы с ними делаете? Откажитесь от них. То же самое касается Java GC. Когда на какой-либо объект не ссылаются через какой-либо объект или он недоступен, он получит следующий раз при запуске gc. Хороший способ убедиться в этом - открыть jvisualvm и продолжать отслеживать строковый литерал, а затем запустить gc. Вы бы видели вещи в режиме реального времени.

Надеюсь, это поможет ..!

...