2017-01-29 21 views
0

я invesigate WeakHashMap код Ource иметь больше знаний о WeakReferenceКак WeakHashMap работает под капотом

Я обнаружил, что запись выглядит следующим образом:

private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> { 
     V value; 
     final int hash; 
     Entry<K,V> next; 

     /** 
     * Creates new entry. 
     */ 
     Entry(Object key, V value, 
       ReferenceQueue<Object> queue, 
       int hash, Entry<K,V> next) { 
      super(key, queue); 
      this.value = value; 
      this.hash = hash; 
      this.next = next; 
     } 
     ... 

Таким образом, когда мы создаем новую запись мы вызываем super(key, queue);. Это WeakReference конструктор. Насколько я понял, после объект будет собран GC, новая ссылка (я считаю, что это должна быть ссылка на key) появится в очереди.

Также я заметил метод, который вызывает на каждой операции:

/** 
    * Expunges stale entries from the table. 
    */ 
    private void expungeStaleEntries() { 
     for (Object x; (x = queue.poll()) != null;) { 
      synchronized (queue) { 
       @SuppressWarnings("unchecked") 
        Entry<K,V> e = (Entry<K,V>) x; 
       int i = indexFor(e.hash, table.length); 

       Entry<K,V> prev = table[i]; 
       Entry<K,V> p = prev; 
       while (p != null) { 
        Entry<K,V> next = p.next; 
        if (p == e) { 
         if (prev == e) 
          table[i] = next; 
         else 
          prev.next = next; 
         // Must not null out e.next; 
         // stale entries may be in use by a HashIterator 
         e.value = null; // Help GC 
         size--; 
         break; 
        } 
        prev = p; 
        p = next; 
       } 
      } 
     } 
    } 

Похоже, мы получаем (Entry<K,V>) из очереди. Я не знаю, как это объяснить (первый вопрос). этот код:

public static void main(String[] args) throws InterruptedException { 
    StringBuilder AAA = new StringBuilder(); 
    ReferenceQueue queue = new ReferenceQueue(); 
    WeakReference weakRef = new WeakReference(AAA, queue); 
    AAA = null; 
    System.gc(); 
    Reference removedReference = queue.remove(); 
    System.out.println(removedReference.get()); 
} 

всегда выдает нуль, поскольку объект уже собранные с помощью ГХ

Кроме того, для меня это было странно, что мы можем иметь ссылку на объект, который уже был собран с помощью ГХ. На самом деле я ожидаю, что ссылка должна появиться в очереди, но я не мог прочитать что-то значимое, потому что объект уже собран (второй вопрос).

+0

@downvoter, я добавил явно текст, который я хочу уточнить – gstackoverflow

+0

рассмотрели ли вы другие вопросы, касающиеся ReferenceQueue? – the8472

+0

@ the8472 Я не видел связанный тег – gstackoverflow

ответ

0

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

дает вам ссылочные экземпляры, помещенные в очередь через конструктор ссылок. В этом случае это Entry<K,V> extends WeakReference<Object>.

На самом деле я ожидаю, что ссылка должна появиться в очереди, но я не мог читать что-то значимое, потому что объект уже собрало

Вы сам Reference объекта, который вы можете использовать, чтобы сделать некоторые очистки, либо через подклассы или путем сопоставления его с дополнительными данными, например через вспомогательное устройство Map. Судья, которого вы можете получить через get, пока он еще жив, не имеет значения, сам объект Reference.

+0

Почему я помещаю ** Запись **? – gstackoverflow

+0

Как gc понимает этот ключ, связанный со входом, а не только с WeakReference? – gstackoverflow

+0

Это новые вопросы. Я предлагаю прочитать javadocs или изучить другие примеры, относящиеся к ReferenceOutue на SO, есть гораздо более простые примеры, чем 'WeakHashMap' – the8472

0

Очередь возвращает самый ссылочный объект, который вы создали ранее. Так с примером кода, после выполнения

Reference removedReference = queue.remove(); 

выражение removedReference == weakRef будет вычисляться true, так как это единственный эталонный объект вы когда-либо созданных. С помощью этого теста вы уже можете сделать вывод, что объект, ранее ссылающийся на AAA, был собран из-за идентичности ссылочного объекта, поэтому вы уже прочитали «что-то значимое».

Если вы хотите связать с ним дополнительную информацию, жизнеспособным способом является создание подкласса WeakReference, что и есть то, о чем говорит WeakHashMap.Entry.В своем конструкторе он вызывает super(key, queue);, который не отличается от вашего выражения new WeakReference(AAA, queue), первый аргумент указывает объект с низкой ссылкой.

Так сборщик мусора епдиеие специализированный WeakReference, т.е. Entry, объект, если его референт (key) стал недостижимым. На этом этапе ключ больше не может быть извлечен, т. Е. Его метод get() вернет null, но метод expungeStaleEntries() в любом случае не заинтересован в ключе. Он хочет удалить экземпляр Entry из таблицы, позволяя сборщику мусора восстановить сам экземпляр Entry и, возможно, ссылочное значение, если на нем нет другой ссылки. Это помогает, что этот подкласс запомнил ранее вычисленный хеш-код, поэтому карте не нужно искать линейно.