문제

In Java there is a data structure called a WeakHashMap that stores weak references as keys. Whenever the weak references are taken out of memory the entry is removed from the map.

If I have a data structure such as a Stack or a Set where I am storing weak references, will their entries be automatically removed when the weak reference is taken out of memory?

Below is an example of a Stack that stores weak references.

Stack<WeakReference<Object>> objStack = new Stack<WeakReference<Object>>();
도움이 되었습니까?

해결책

Yes. What you're describing is a property of weak references in general, not WeakHashMap specifically.

From the API:

Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object...

다른 팁

Better late than never.

This is not how weak references work. The WeakReference-object will always be there, but its get()-method may return the original object or null (if the original object was GC:ed).

This means your Stack will always contain a WeakReference-object.

Here's a verbose test I did (however it depends on the JVM doing GC in the middle, which may or may not happen "on command" - try to add some more System.gc():s if it doesn't happen):

public static void main(String[] args) {
    // Set up
    Object object = new Object();
    final WeakReference<Object> weakReference = new WeakReference<>(object);
    final Stack<WeakReference<Object>> references = new Stack<>();      
    references.add(weakReference);

    // Before
    System.out.println("Before:");

    references.forEach(r -> {
        System.out.println("Reference: " + r);
        System.out.println("Object: " + r.get());
    });

    // GC
    object = null;

    System.gc();
    System.gc();
    System.gc();

    // After
    System.out.println("After:");
    references.forEach(r -> {
        System.out.println("Reference: " + r);
        System.out.println("Object: " + r.get());
    });
}

The output:

Before:
Reference: java.lang.ref.WeakReference@238e0d81
Object: java.lang.Object@31221be2
After:
Reference: java.lang.ref.WeakReference@238e0d81
Object: null

Your best approach is probably to just ignore entries where get() returns null once you "pop" them.

Side note: My first test was with a String-object, which never got GC:ed. This is because strings in Java are "interned" (see String.intern()) meaning there is a hidden cache of static strings that are reused. A string will never be GC:ed, unless that pool of strings are full (or something along that line...) I think strings are the only Java object with this "special" characteristic but I'd recommend always using custom made objects in a WeakReference to make sure it gets GC:ed correctly.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top