Подтвердить что ты не робот

Сбор мусора Java на массивах на основе стека

Предположим, что у меня есть следующий код:

public void process() {
    byte[] data = new byte[size]; 
    ... // code that uses the above data
    longProcess(); // a very long running process that does not use the data.
}

Предполагая, что данные не связаны нигде в программе, является ли JVM достаточно умным, чтобы данные собирались в мусор, пока длительный процесс все еще работает?

Если нет, добавит

data = null;

до того, как длительный процесс позволит это произойти?

4b9b3361

Ответ 1

Это зависит от JVM. Версии Oracle JVM, которые я пробовал (1.6.0_41 и 1.7.0_09), по умолчанию не выполняют эту оптимизацию. Тем не менее, 1.7.0_09 выполняет его при включении агрессивных оптимизаций.

Вот тест, который я провел:

public class Main {
    public static int g() {
        int n = 100000;
        int arr[][] = new int[n][];
        for (int i = 0; i < n; ++i) {
            try {
                arr[i] = new int[100000];
            } catch (OutOfMemoryError ex) {
                return i;
            }
        }
        return -1;
    }
    public static void f1() {
        int arr[] = new int[1000000];
        System.out.println(g());
    }
    public static void f2() {
        int arr[] = new int[1000000];
        arr = null;
        System.out.println(g());
    }
    public static void main(String[] argv) {
        for (int j = 0; j < 2; ++j) {
            for (int i = 0; i < 10; ++i) {
                f1();
            }
            System.out.println("-----");
            for (int i = 0; i < 10; ++i) {
                f2();
            }
            System.out.println("-----");
        }
    }
}

Используя JVM 1.7 с настройками по умолчанию, f1() последовательно заканчивается после 3195 итераций, тогда как f2() последовательно управляет итерациями 3205.

Изображение меняется, если код выполняется с использованием Java 1.7.0_09 с -XX:+AggressiveOpts -XX:CompileThreshold=1: обе версии могут выполнять 3205 итераций, указывая, что HotSpot выполняет эту оптимизацию в этом случае. Java 1.6.0_41, похоже, не делает этого.

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

Ответ 2

Учитывая, что код написан как написанный, массив, конечно же, не будет мусором, собранным во время выполнения longprocess(), поскольку до сих пор имеется ссылка на массив в стеке. Как только этот массив будет объявлен, он не будет иметь права на сбор мусора, пока все ссылки на него не будут удалены. Ваша строка

data = null;

удалит одну ссылку на него, хотя в зависимости от вашего кода обработки это может быть не единственная ссылка. Если все ссылки удалены, сборщик мусора может очень хорошо собрать эту память массива к моменту завершения longprocess(), хотя это не гарантируется.

Ответ 3

Если ссылки на данные отсутствуют, тогда GC выполнит задание.

Ответ 4

Массив данных будет освобожден из памяти только после завершения технологического процесса. Поэтому, если вы хотите, чтобы компилятор освободил память, вам придется явно добавить в код данные = null.

The Garbage Collector освобождает память, которая не имеет доступной для нее справки, и нет другого способа снова указать на эту память.