Слабая ссылка не собирает мусор?

Я изучал слабые ссылки. И я понял, что все слабые ссылки БУДУТ собирать мусор до того, как произойдет OutOfMemoryError. У меня был простой тест, что-то вроде этого (я знаю, что ловить OOME нехорошо, но просто тест):

Integer weakInt = new Integer(10);
WeakReference<Integer> weakReference = new WeakReference<Integer>(weakInt);

try {
    while (weakReference != null) {
        String[] generateOutOfMemoryStr = new String[999999999];
    }
}
catch (OutOfMemoryError oome) {
   System.out.println(weakReference.get());
}

Я ожидал, что будет напечатано значение null, потому что слабая ссылка ДОЛЖНА быть собрана, но я всегда получаю результат 10.

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


person Basith    schedule 05.06.2011    source источник


Ответы (1)


weakReference сам по себе не станет нулевым... как же так? Однако его цель может стать нулевой.

Я подозреваю, что вы имеете в виду:

while (weakReference.get() != null) {

Более того, я подозреваю, что если вы не установите для самого weakInt значение null, эта локальная переменная предотвратит сборку мусора для объекта Integer.

Более того, я подозреваю, что вы обнаружите, что ваш цикл по-прежнему не закончится, потому что вы, вполне возможно, запрашиваете больше памяти, чем может быть выделено, даже если Integer является сборщиком мусора.

Вот программа, которая демонстрирует ее работу, по крайней мере, на моем компьютере:

import java.lang.ref.*;

public class Test {
    public static void main(String[] args) {
        Integer weakInt = new Integer(10);
        WeakReference<Integer> weakReference = new WeakReference<Integer>(weakInt);

        weakInt = null;
        while (weakReference.get() != null) {
            System.out.println("Looping...");
            String[] generateOutOfMemoryStr = new String[999999];
        }
        System.out.println("Weak reference collected");
    }
}
person Jon Skeet    schedule 05.06.2011
comment
Большое спасибо за это. Просто может быть глупый вопрос :) После того, как вы сделаете weakInt равным нулю, я подумал, что weakReference.get() всегда должен возвращать значение null? ... Но удивительно, что он выполняется пару раз, прежде чем столкнуться с OutOfMemoryError. . - person Basith; 05.06.2011
comment
@Basith: Почему он всегда возвращает ноль? Мы только что установили для переменной значение null. Мы могли бы настроить его так, чтобы он ссылался на другой Integer — это не изменило бы цель weakReference. На данный момент опустим WeakReference из уравнения, предположим, что у нас есть Integer x = new Integer(10); Integer y = x; x = new Integer(20); System.out.println(y); — что вы ожидаете, что это напечатает? - person Jon Skeet; 05.06.2011
comment
хорошо что пример был не Integer wakInt = 10 что бы смешнее. - person bestsss; 06.06.2011
comment
@bestsss: Да, я и сам так думал. Лично я обычно придерживаюсь примера Object, а не углубляюсь в области целых чисел и строк, где вы можете получить большие поведенческие изменения с, казалось бы, небольшими изменениями исходного кода (например, изменение 127 на 128:) - person Jon Skeet; 06.06.2011