Why does WeakHashMap have a strong value reference after the GC?

The key object in WeakHashMap has become inaccessible. And the card must be removed after the GC. But a strong reference to the object of value remains. Why?

The same behavior is observed when displaying the weak guava key.

Expected Result:

...
refKey.get = null
refValue.get = null

But I get the output:

map.keys = []
map.values = []
map.size = 0
refKey.get = null
refValue.get = (123)

code:

import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
import com.google.common.collect.MapMaker;

public class Test {

    static class Number {
        final int number;
        public Number(int number) { this.number = number; }
        public String toString() { return "(" + number + ")"; }
    }

    static class Key extends Number {
        public Key(int number) { super(number); }
    }

    static class Value extends Number {
        public Value(int number) { super(number); }
    }

    public static void main(String args[]) {

        //Map<Key, Value> map = new MapMaker().weakKeys().makeMap();
        Map<Key, Value> map = new WeakHashMap<>();

        Key key = new Key(1);
        Value value = new Value(123);

        map.put(key, value);

        WeakReference<Key> refKey = new WeakReference<>(key);
        WeakReference<Value> refValue = new WeakReference<>(value);

        key = null;
        value = null;

        System.gc();

        System.out.println("map.keys = " + map.keySet());
        System.out.println("map.values = " + map.values());
        System.out.println("map.size = " + map.size());
        System.out.println("refKey.get = " + refKey.get());
        System.out.println("refValue.get = " + refValue.get());

    }

}

UPD:

I tried to execute the GC in jConsole and jcmd, but the output was not changed.

+5
source share
3 answers

WeakHashMapcontains instances Map.Entrythat reference the key using WeakReference(in fact, in OpenJDK / Oracle JDK it directly extendsWeakReference ).

GC , , , : , , .

OpenJDK expungeStaleEntries() ReferenceQueue, :

  • size()
  • resize()
  • getTable() , get() put()

, , WeakHashMap, , size() .

, , .

, .

+5

GC Jconsole .

    System.gc();

    try {
        while (refValue.get() != null) {
            System.out.println("map.keys = " + map.keySet());
            Thread.sleep(5000);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println("map.keys = " + map.keySet());
    System.out.println("map.values = " + map.values());
    System.out.println("map.size = " + map.size());
    System.out.println("refKey.get = " + refKey.get());
    System.out.println("refValue.get = " + refValue.get());

- , map.keySet() , , refValue null.

+2

GC java. . , System.gc(). System.gc() , , FULL ( ), .

In jdk 1.7, you can use the command below to make gc run

jcmd <pid> GC.run

Get processid with jps

+1
source

Source: https://habr.com/ru/post/1624970/


All Articles