Do SoftReference
and WeakReference
really only help when created as instance variables? Is there any benefit to using them in method scope?
The other big part is ReferenceQueue
. Besides being able to track which references are determined garbage, can Reference.enqueue()
be used to forcibly register an object for garbage collection?
For example, would it be worth to create a method that takes some heavy memory resources (held by strong references) in an object and creating References to enqueue them?
Object bigObject; public void dispose() { ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); WeakReference<Object> ref = new WeakReference<Object>(bigObject, queue); bigObject = null; ref.enqueue(); }
(Imagine that Object in this case represents an object type that uses a lot of memory... like BufferedImage
or something)
Does this have any realistic effect? Or is this just a waste of code?
Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used to schedule post-mortem cleanup actions.
Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed. Weak references are most often used to implement canonicalizing mappings. Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable.
One common idiom with reference queues is to e.g. subclass WeakReference
to attach information that's needed to clean up things, and then to poll a ReferenceQueue
to get cleanup tasks.
ReferenceQueue<Foo> fooQueue = new ReferenceQueue<Foo>(); class ReferenceWithCleanup extends WeakReference<Foo> { Bar bar; ReferenceWithCleanup(Foo foo, Bar bar) { super(foo, fooQueue); this.bar = bar; } public void cleanUp() { bar.cleanUp(); } } public Thread cleanupThread = new Thread() { public void run() { while(true) { ReferenceWithCleanup ref = (ReferenceWithCleanup)fooQueue.remove(); ref.cleanUp(); } } } public void doStuff() { cleanupThread.start(); Foo foo = new Foo(); Bar bar = new Bar(); ReferenceWithCleanup ref = new ReferenceWithCleanup(foo, bar); ... // From now on, once you release all non-weak references to foo, // then at some indeterminate point in the future, bar.cleanUp() will // be run. You can force it by calling ref.enqueue(). }
For example, the internals of Guava's CacheBuilder
implementation when weakKeys
are selected uses this approach.
If an object has only WeakReference
s (or no references whatsoever!) towards it, it can be garbage collected whenever Java needs to make more room in memory. So, you use WeakReference
s whenever you want an object to remain in memory, but you don't need it to remain THAT badly (e.g. if Java needs to garbage collect it, no problem, you can get it back somehow and in the mean time Java has better performance)
Enqueuing a WeakReference
allows you to iterate the ReferenceQueue
and determine which references have been garbage collected and which have not. That's all - so only do it if you need to know this.
Read more: http://weblogs.java.net/blog/2006/05/04/understanding-weak-references
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With