Слабая ссылка на коллекцию в Java - PullRequest
0 голосов
/ 11 декабря 2018

Предыстория

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

List<Bob> list = cache.asList();
List<Bob> otherList = cache.asList(); // use from cache, if still available

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

Вопрос

Если у меня естьWeakReference<List<Bob>> хранится в моем классе, что произойдет, если один из элементов станет слабо достижимым (что означает, что список слабо доступен)?Возможно ли, что GC решит просто собрать элемент внутри списка или будет искать все другие слабо достижимые объекты, ссылающиеся на него, а также собирать их, в этом случае список?

Проблема будет, еслиGC собрал элемент списка, и затем мы снова пытаемся получить доступ к списку (если это вообще возможно), что произойдет?

Разъяснения

Я неинтересуясь достижимостью списка, я знаю, что список находится внутри WeakReference и что элементы не имеют отношения к его достижимости.Я забочусь о конкретном состоянии, в котором и список, и элемент списка слабо достижимы, и возможно ли, что GC собирает только элемент, но не сам список.Что именно GC делает в этом конкретном сценарии?

Ответы [ 3 ]

0 голосов
/ 11 декабря 2018

В предоставленном случае (WeakReference<List<Something>>) у вас есть только такой возможный сценарий:

public class Test {

    private WeakReference<List<String>> listWeakReference;

    public Test(final WeakReference<List<String>> listWeakReference) {
        this.listWeakReference = listWeakReference;
    }

    public static void main(String[] args) {
        List<String> testList = Arrays.asList("a", "b", "c");

        Test test = new Test(new WeakReference<>(testList));

        // Initial check
        System.out.println(test.listWeakReference.get());

        // Call gc and check
        System.gc();
        System.out.println(test.listWeakReference.get());

        // Remove reference and call gc
        testList = null;
        System.gc();
        System.out.println(test.listWeakReference.get());
    }
}
0 голосов
/ 11 декабря 2018

Во-первых, SoftReference лучше для кэшей, и даже это не очень хорошо.

WeakReference может быть освобождено немедленно ссылка становится слабо достижимой.Тем не менее, это может не произойти, пока не произойдет какое-то время - то есть, это не происходит во время обширного тестирования, но происходит в процессе производства.Веселые времена.NetBeans использовал это для кэширования файлов.Конечно, остальная часть кода ожидала, что кеширование так захватит и выпустит ссылки с невероятной частотой.После некоторого времени использования приложения оно внезапно забьет файловый ввод-вывод и станет непригодным для использования.

Для лучшей производительности вам нужно явно оценить, сколько памяти использует процесс, и освободить при необходимости.Не легко.

Вернуться к вопросу.Сбор содержимого WeakReferenceSoftReference - это двухфазная операция. Первый этап просто очищает Reference (и очереди, если вы его используете). Связанная память не собирается. Память может быть воскрешена черезфинализатор. WeakReference навсегда очищается и ставится в очередь, он не сбрасывается. Только когда объект полностью недоступен, связанная память может быть собрана как отдельная фаза.

Не бойтесь, Java - безопасный для памяти (ошибки исключены).

0 голосов
/ 11 декабря 2018

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

Таким образом, нет проблем с кэшированием списка со слабой ссылкой, потому что это будет либо сборщик мусора полностью, либо не совсем.

...