2016-07-07 12 views
3

Я кеш, реализованных с WeakHashMap, как это:мусора коллектор работа с 2 WeakHashMaps

private static WeakHashMap<Object, WeakReference<Object>> objects = new WeakHashMap<>(); 

У меня есть экземпляр класса Город:

City c = new City(); 

я теперь добавить этот экземпляр моей карте например:

objects.put(c, new WeakReference<Object>(c)); 

В соответствии с реализацией jvm WeakHashMap, если у ключа нет сильных ссылок на он удаляется с карты (в свободное время).
Итак, если мой объект «c» больше не используется в программе, он будет удален с карты «объекты».
Пока, так хорошо.

Но что произойдет, если у меня есть две карты?

private static WeakHashMap<Object, WeakReference<Object>> objects1 = new WeakHashMap<>(); 
private static WeakHashMap<Object, WeakReference<Object>> objects2 = new WeakHashMap<>(); 
City c = new City(); 
objects1.put(c, new WeakReference<Object>(c)); 
objects2.put(c, new WeakReference<Object>(c)); 

Будет ли GC собирать объект «c» в этом случае?

+0

Если Косые решает воспользоваться объектом, ** всех ** слабых ссылок на него будут соответствующим образом аннулированы. –

+0

Почему вы обертываете значение HashMap в WeakReference? вы не должны этого делать, вы можете иметь нулевые значения в этом случае –

+0

@EliaRohana Он не может быть пустым, если он используется где-то еще. – AndreyP

ответ

3

Возьмите лист бумаги, нарисуйте график с объектами как вершинами, ссылками как ребрами.

Если вы не можете найти путь к сильным ребрам из корня GC (например, статическое поле или локальную переменную в стеке) к объекту в equestion, то он не будет сильно доступен и, следовательно, будет иметь право на GC.

+0

Таким образом, у WeakHashMap нет сильных краев с ключами? – AndreyP

+1

Вы читали javaadocs [WeakHashMap] (https://docs.oracle.com/javase/8/docs/api/java/util/WeakHashMap.html)? – the8472

+0

Ключи слабы, спасибо – AndreyP

0

Слабый слаб, он не станет сильным, если к нему присоединяется другой слабый.

Это будет сбор мусора, если нет другой сильной ссылки. Без сомнений.

1

Для этого он будет собирать его (когда начинается GC), поскольку его все еще ссылаются на WeakReference, а не на сильную ссылку, независимо от того, сколько ссылок WeakReferences ссылается на него.

Вы можете прочитать здесь: WeakReference WeakReference

Вот пример, чтобы продемонстрировать это:

public class WeakHashMapExample { 

    //strongly reference key to prevent GC from collecting it 
    private static final Key stronglyRefKey1 = new Key(1); 

    public static void main(String[] args) throws InterruptedException { 

    WeakHashMap<Key, String> cache1 = new WeakHashMap<>(); 
    WeakHashMap<Key, String> cache2 = new WeakHashMap<>(); 

    //adding same keys 
    Key key2 = new Key(2); 
    cache1.put(stronglyRefKey1, "val 1"); 
    cache1.put(key2, "val 2"); 
    cache2.put(stronglyRefKey1, "val 1"); 
    cache2.put(key2, "val 2"); 
    key2 = null; // remove strong reference 

    //may or may not print Key(2) key, depends if GC starts at this point 
    System.out.println("cache1 = " + cache1); 
    System.out.println("cache2 = " + cache2); 

    //for GC to start so all weak reference should be cleared 
    System.gc(); 

    //after GC ha been ran, key(2) will be removed because its only referenced by weak reference of the WeakHashMap 
    System.out.println("cache1 = " + cache1); 
    System.out.println("cache2 = " + cache2); 
    } 

    private static class Key{ 
    int value; 

    private Key(int value) { 
     this.value = value; 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (o == null || getClass() != o.getClass()) return false; 

     Key key = (Key) o; 

     if (value != key.value) return false; 

     return true; 
    } 

    @Override 
    public int hashCode() { 
     return value; 
    } 

    @Override 
    public String toString() { 
     return "Key{value=" + value +'}'; 
    } 
    } 
} 
+0

В приведенном выше примере вы использовали 2 разных экземпляра для клавиши (2). Что, если это был тот же самый экземпляр? Если WeakHashMap имеет сильную ссылку на ключ, GC не будет собирать Key (2). – AndreyP

+0

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