Tiller
Tiller

Reputation: 476

Weak references and anonymous classes

I'm in a situation where I have a static list caching some references. As this is a static list, I want to use WeakReference so I don't keep my objects in memory uselessly.

The issue - I think - I have is that one of the references is an anonymous class. My fear is that if I store the anonymous class as a WeakReference, it might be collected really quickly, and if I store the anonymous class as a strong reference, it will hold a reference to the class that constructed the anonymous class.

I don't know if my explanation is clear, so here is a piece of code:

public interface Callback {
    void call();
}

public class A {
    public void doIt() {
        B.register(this, new Callback() {
            public void call() {
                // do something
            }
        });
    }
}

public class B {
    private static final List<Item> ITEMS = new LinkedList<>();

    public static void register(Object key, Callback callback) {
        Item item = new Item();
        item.key = new WeakReference<>(key);

        // ??
        item.callback = new WeakReference<>(callback);

        ITEMS.add(item);
    }

    private static class Item {
        private WeakReference<Object> key;
        private WeakReference<Callback> callback;
    }
}

Basically, if in Item 'callback' is a weak reference, it might be garbage collected before I even get the chance to use it. And if in Item 'callback' is a standard reference, the instances of 'A' will never be garbage collected.

So my first question: is my understanding right? Second question: is there a way to make it work or do I have to change the design?

Thanks.

Upvotes: 5

Views: 1431

Answers (1)

the8472
the8472

Reputation: 43052

If Callback is a functional interface you can use a lambda instead. Lambdas only capture the variables they reference. So if the lambda is a pure function, a static method reference or only references local variables it will not capture this. If you reference this, an instance method or instance field then it will capture.

The same can be achieved by replacing the anonymous class with an static inner class or a separate class.

It is unclear why you're using two separate weak references per Item. You could simply keep the item itself in a weak reference and have strong refs to key and callback, they would be effectively weak when item itself is only weakly reachable.

In general you should reason about paths from GC roots. If an object is only reachable from a GC root with a path of references where even a single one of the references is weak then the whole subgraph is only weakly reachable and thus eligible for collection.

Basically, to have my item released only when 'A' need to be released.

Then a WeakHashMap<A, Callback> is what you want. Just ensure that Callback does not reference A.

Upvotes: 3

Related Questions