Запретить сборку мусора перед другими объектами - PullRequest
1 голос
/ 28 февраля 2020

У меня есть массив слабых ссылок на дополнительные объекты, например, так:

public class Foo{
    WeakReference<WeakReference<Bar>[]> cache;
}
public class Bar{
    private final WeakReference<Bar>[] ownerCache;
}

Сам массив слабо упоминается по причинам, о которых я не буду go прямо сейчас. Я хочу убедиться, что это не мусор, прежде чем ЛЮБЫЕ объекты Bar достижимы из него. Другими словами, он должен существовать в памяти до тех пор, пока существует любой объект Bar, к которому можно добраться из него. Затем, если больше нет объектов Bar, мне лучше, если массив также будет собирать мусор. (Объекты Bar могут или не могут быть сильно доступны из других мест.) Я сделал это, обратившись к массиву кэша в поле внутри всех объектов Bar. Если поля достаточно для того, чтобы массив был доступен, он не является сборщиком мусора. Однако мой код никогда не использует это поле, и я не могу его опубликовать c. (Я получаю «неиспользуемое» предупреждение об этом.) Я боюсь, что существование такого поля прекращается либо во время компиляции, либо во время выполнения, либо оно может получить специальную обработку от сборщика мусора, о котором я не знаю.

Это правильное решение? Достигает ли это решение того, чего я хочу, независимо от сборщика мусора или реализации JVM? Если нет, то какой метод лучше?

1 Ответ

1 голос
/ 28 февраля 2020

Вот пара идей.

Если вы управляете классом Bar, и на каждый экземпляр ссылается не более одного массива, вы можете добавить ссылку на экземпляр Bar на массив. Достижимые экземпляры Bar будут препятствовать сбору массива.

В качестве альтернативы вы можете:

  1. Создать очередь ссылок для слабых ссылок на экземпляры Bar.

    ReferenceQueue<Bar> m_refQueue = new ReferenceQueue<>();
    
  2. Создайте каждую WeakReference со ссылкой на эту очередь.

    new WeakReference<Bar>( myBar, m_refQueue );
    
  3. Периодически опрашивайте эту очередь на наличие доступных коллекционных экземпляров и удаляйте их из вашей коллекции. ,

  4. Вы можете сделать саму коллекцию структурой данных с изменяемым размером, избегая необходимости собирать ее.

    public class Foo {
       final @Nonnull List<WeakReference<Bar>> cache = new ArrayList<>();
    
       // Or you could use an IdentityHashSet from a third-party library.
    }
    

РЕДАКТИРОВАТЬ

Как подсказывает @Holger ниже, если упорядоченный список ссылок не нужен, ваша коллекция WeakReference может быть java .util.WeakHashMap , используемой как набор , Ключи являются слабыми ссылками; значения могут быть нулевыми. Карта представляет собой структуру данных с изменяемым размером, поэтому вы можете просто хранить обычную ссылку на карту.

    public class Foo {
       final @Nonnull WeakHashMap<WeakReference<Bar>,Object> cache
          = new WeakHashMap<>();
...