1

In the following code...

public class MyObject {
    public static Map<String, WeakReference<MyObject>> cache = new HashMap<>();
    public static ReferenceQueue<MyObject> queue = new ReferenceQueue<>();
    public MyObject(String... args) {
        //define variables...
        cache.put(args[0], new WeakReference<>(this, queue));
    }
    // getters and setters
}

If MyObjects are continuously created, since cache contains only weak references, will the garbage collector eventually remove items from cache? Will those items become null? Is there a better way of caching objects? My objective is to store discord messages so I don't have to fetch them again.

AJ_4real
  • 167
  • 6
  • Should answer your question: [Will a HashMap> potentially cause a memory leak if not explicitly cleaned up?](//stackoverflow.com/a/46239003) – Tom Jul 18 '21 at 01:29
  • what is the point in defining an explicit `ReferenceQueue` in your example? – Eugene Jul 18 '21 at 01:29
  • Why not use a [WeakHashMap](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/WeakHashMap.html)? – Bohemian Jul 18 '21 at 01:47

2 Answers2

4

WeakReferences (once understood) are not magic, and often even easily miss-used. One such example is in your case. First of all of declaring an explicit ReferenceQueue<MyObject> is kind of no use to you, which implies that you want to push code "from here and there" to make it work; this is not a good strategy.

The idea of a week references is not complicated. Once a GC cycle sees that some instance is weakly referenced (non strong references to it exist), it can simply reclaim that memory and start returning null from WeakReference::get. To get to your example, when some MyObject instance is going to be weakly referenced, your:

map.get("whatever").get()

will start to return null. But the Map.Entry will still be present in the HashMap. There is no auto-magic clean-up. Even WeakHashMap is no magic.

There are many "other" ways to cache things, it's complicated to say without more details, which would be appropriate for your case. There is guava, a last-recently used cache like LinkedHashMap, etc.

Eugene
  • 117,005
  • 15
  • 201
  • 306
2

will the garbage collector eventually remove items from cache?

The GC will eventually break the references, and enqueue them on the reference queue.

It won't automatically remove the entries (with broken references) from the map. To do that, you would need to add something to consume the reference queue and expunge the stale entries from the map.

Will those items become null?

See above. (It is unclear what you mean by this ...)

Is there a better way of caching objects?

Possibly, use a WeakHashMap. It deals with the problem of removing the broken references. But the criterion for breaking the reference is different. In that case, the reference is broken when the >>key<< is found to be not weakly reachable.

Another alternative would be to use an LRU cache implemented using LinkedHashMap.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216