102

Possible Duplicate:
Weak references - how useful are they?

Since weak references can be claimed by the garbage collector at any time, is there any practical reason for using them?

Community
  • 1
  • 1
user496949
  • 83,087
  • 147
  • 309
  • 426
  • 3
    http://weblogs.java.net/blog/2006/05/04/understanding-weak-references - weak, soft and phantom references explained – Piotr Gwiazda Jan 09 '12 at 15:20
  • 1
    Events (callbacks) are a good one - events should always have weak-references. Unfortunately, in C#, even though events are a language-feature, they always use strong-references. This is a mistake of the language, and has caused lots of hard-to-find memory leaks in programs (there are libraries which fix this problem *[and several other problems with events]*, such as CAB or the open source equivalent, [bbv.Common.EventBroker](http://www.codeproject.com/KB/dotnet/EventBroker.aspx)). – BlueRaja - Danny Pflughoeft Jan 09 '12 at 17:39
  • 2
    @BlueRaja-DannyPflughoeft, making the event references weak without doing anything else changes memory leak problems to non-deterministic premature deallocation problems, which are much worse. – Rotsor Jan 09 '12 at 18:27
  • @Rotsor: There is a simple solution to that, on the VM's side - during garbage collection, consider any object currently running an event as having a reference. But there is no need to bring up that minor implementation detail here... – BlueRaja - Danny Pflughoeft Jan 09 '12 at 19:01
  • @BlueRaja-DannyPflughoeft Let us discuss this in [chat](http://chat.stackoverflow.com/rooms/6560/events-should-always-have-weak-references-or-should-they) – Rotsor Jan 09 '12 at 19:17
  • how about just turning the previous activity reference to null after the making the callback? – Ahmad Shahwaiz Jan 04 '18 at 06:14

8 Answers8

53

If you want to keep a reference to something as long as it is used elsewhere e.g. a Listener, you can use a weak reference.

WeakHashMap can be used as a short lived cache of keys to derived data. It can also be used to keep information about objects used else where and you don't know when those objects are discarded.

BTW Soft References are like Weak references, but they will not always be cleaned up immediately. The GC will always discard weak references when it can and retain Soft References when it can.

There is another kind of reference called a Phantom Reference. This is used in the GC clean up process and refers to an object which isn't accessible to "normal" code because its in the process of being cleaned up.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Using weak references as a cache does have its problems though: [See this](http://www.azulsystems.com/blog/cliff/2007-08-30-why-weakhashmap-sucks) That's specific to weak HashMap, but the general problem (using weak references as a cache) is the same to some degree. – Voo Jan 09 '12 at 17:11
  • @Voo Agree than using WeakReferences are not as good as SoftReferences for a cache, however both have problems. – Peter Lawrey Jan 09 '12 at 17:16
  • Yeah soft references could help with the problem, but afaik the language doesn't really make any hard guarantees about them (ie they could be handled just as weak references) so then we depend on a specific GC implementation to avoid the problems. And as you say there are problems with softrefs either: (assume naive impl. - no idea how hotspot/ibm handle them atm!) If we just add objects until we run out of memory, then remove all of them at once, that isn't perfect either. – Voo Jan 09 '12 at 17:24
  • Yes, you could find your application is running fine most of the time and suddenly all the SoftReferences get cleaned up at once and you have nothing cached. (Usually after a full GC) so just at the time you want your application to be fastest to catch up (as it just paused for a while) everything has to be brought back into the cache. i.e. it works well most of the time, except when you need it the most. :( One way around this is to have a small, fixed size cache of strong references and a second tier cache of weak/soft references. – Peter Lawrey Jan 09 '12 at 17:28
  • 1
    Yeah :( My solution to the caching problem so far was to just use a strong cache of a particular size and fine tune the cache size if necessary. Far from optimal if the program will run on lots of different configurations - in that case the tiered approach may be worth the additional complexities. – Voo Jan 09 '12 at 18:45
  • 1
    Its worth having a look at LinkedHashMap as it supports a simple LRU cache. – Peter Lawrey Jan 09 '12 at 19:00
  • 1
    @Voo, you can pin a number of the most used entries but if you can do that, why bother just do all the stuff yourself – bestsss Jan 16 '12 at 02:51
  • @bestsss I assume you mean why use the tiered approach Peter proposes at all? The advantage I see compared to a single fixed size cache is that we have some guarantees about performance, but can still use the additional memory for speedups - that seems useful. Not the pathological behavior of a sole soft referenced cache, but we still use the memory available – Voo Jan 16 '12 at 14:43
  • 1
    well, a good cache should not rely on a fixed size only but employ some usage statistics beyond LRU. If you do that, you dont need soft references any more. Also soft references behave horrible if you retain direct buffers or any other native objects. They are useful for *heap* memory intense caches only. – bestsss Jan 16 '12 at 15:53
30

Since weak reference can be claimed by garbage collector at any time, is there any practical reason to use it?

Of course there are practical reasons to use it. It would be awfully strange if the framework designers went to the enormous expense of building a weak reference system that was impractical, don't you think?

I think the question you intended to ask was:

What are realistic situations in which people use weak references?

There are many. A common one is to achieve a performance goal. When performance tuning an application one often must make a tradeoff between more memory usage and more time usage. Suppose for example there is a complex calculation that you must perform many times, but the computation is "pure" -- the answer depends only on the arguments, not upon exogenous state. You can build a cache -- a map from the arguments to the result -- but that then uses memory. You might never ask the question again, and that memory is would then be wasted.

Weak references possibly solve this problem; the cache can get quite large, and therefore time is saved if the same question is asked many times. But if the cache gets large enough that the garbage collector needs to reclaim space, it can do so safely.

The downside is of course that the cleanup policy of the garbage collector is tuned to meet the goals of the whole system, not your specific cache problem. If the GC policy and your desired cache policy are sufficiently aligned then weak references are a highly pragmatic solution to this problem.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 7
    The problem with this particular scenario is that you are hoping the GC will behave in a desirable way and do some of the work that is inherent to your optimization algorithm. I think in the most common GC policy implementations a weak reference to an object that has no strong reference will be blown away very quickly- usually on the first GC pass. I would even say its better to implement your own tracking of these 'answers' using strong references and drop them explicitly using your own domain knowledge and logic. – Abdul Hfuda Jan 09 '12 at 17:18
  • 1
    [Why WeakHashMap Sucks](http://www.azulsystems.com/blog/cliff/2007-08-30-why-weakhashmap-sucks) or the downsides of using weak references as a cache. Obviously no real problem with stop the world GC that runs only rarely, but we're moving away from that. You are hinting at that problem in your last paragraph, but the thing is: I don't want to use an inferior GC just so that I can use weak hashmaps - and at least in Java those new concurrent GCs are great (no idea how far .NET is down the road there, but I'm sure they're going in the same direction) – Voo Jan 09 '12 at 17:19
  • 11
    Weak (or Soft) references should not be used as quick&dirty caches, aggressive GCs may evict the references almost immediately and the gain would be zero. Using references as cache would make the program dependent on the GC algorithm or just the parameters for the GC and can not be predicted reliably. – bestsss Jan 16 '12 at 02:45
  • 1
    @Voo, WeakHashMap cannot be used as cache at all, you want the values to be soft, not the keys. (Soft)RefMaps do work as cache and do that pretty well... except when the memory becomes tight and the application goes into a vicious cycle: due to failing caches. Back in the day (~2003) I used to like the quick&dirty caches via soft references but they are just unreliable, esp. w/o control over the GC and caches shall not be a driving force how to configure the GC. – bestsss Jan 16 '12 at 02:48
  • 1
    Why are you suggesting that caching of objects to which no other references exist is a practical use for WeakReference? A much better use, which does not presume that garbage collections are infrequent, is management of notifications. An object may want to update another object when something happens as long as anyone is interested in seeing those updates, but not want to have that other object kept around merely for the purpose of receiving updates once nobody cares about them anymore. – supercat May 11 '12 at 22:51
  • Maybe the original inclusion of weak references in Java was done to provide a band-aid to limited memory in those days. Things have evolved significantly since then and using more robust techniques that don't rely upon some iffy garabage collector suddenly taking out your reference at some random time is a better approach. I have written several mobile apps in Java and have yet to see a need for weak references. – Johann Jan 13 '15 at 16:06
  • That URL doesn't seem to work anymore. http://www.cliffc.org/blog/2007/08/30/why-weakhashmap-sucks/ – TheBuzzSaw Nov 23 '15 at 20:01
16

If a WeakReference is the only reference to an object, and you want the object to hang around, you should probably be using a SoftReference instead.

WeakReferences are best used in cases where there will be other references to the object, but you can't (or don't want to have to) detect when those other references are no longer used. Then, the other reference will prevent the object from being garbage collected, and the WeakReference will just be another way of getting to the same object.

Two common use cases are:

  1. For holding additional (often expensively calculated but reproducible) information about specific objects that you cannot modify directly, and whose lifecycle you have little control over. WeakHashMap is a perfect way of holding these references: the key in the WeakHashMap is only weakly held, and so when the key is garbage collected, the value can be removed from the Map too, and hence be garbage collected.
  2. For implementing some kind of eventing or notification system, where "listeners" are registered with some kind of coordinator, so they can be informed when something occurs – but where you don't want to prevent these listeners from being garbage collected when they come to the end of their life. A WeakReference will point to the object while it is still alive, but point to "null" once the original object has been garbage collected.
Bubletan
  • 3,833
  • 6
  • 25
  • 33
Bill Michell
  • 8,240
  • 3
  • 28
  • 33
13

We use it for that reason - in our example, we have a variety of listeners that must register with a service. The service keeps weak references to the listeners, while the instantiated classes keep strong references. If the classes at any time get GC'ed, the weak reference is all that remains of the listeners, which will then be GC'ed as well. It makes keeping track of the intermediary classes much easier.

Noah
  • 1,966
  • 1
  • 14
  • 29
8

The most common usage of weak references is for values in "lookup" Maps.

With normal (hard) value references, if the value in the map no longer has references to it elsewhere, you often don't need the lookup any more. With weakly referenced map values, once there are no other references to it, the object becomes a candidate for garbage collection

The fact that the map itself has a (the only) reference to the object does not stop it from being garbage collected because the reference is a weak reference

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • 3
    *The most common usage...*, this is untrue. could be true for soft one but definitely not weak ones. WeakReferences are used where retaining the real reference would lead to a leak. – bestsss Jan 16 '12 at 02:52
3

A weak reference is a reference that does not protect the referent object from collection by a garbage collector.

  • An object referenced only by weak references is considered unreachable (or "weakly reachable") and so may be collected at any time.
  • Weak references are used to avoid keeping memory referenced by unneeded objects. Some garbage-collected languages feature or support various levels of weak references, such as Java, C#, Python, Perl, PHP or Lisp.
  • Garbage collection is used to reduce the potential for memory leaks and data corruption. There are two main types of garbage collection: tracing and reference counting. Reference counting schemes record the number of references to a given object and collect the object when the reference count becomes zero. Reference-counting cannot collect cyclic (or circular) references because only one object may be collected at a time. Groups of mutually referencing objects which are not directly referenced by other objects and are unreachable can thus become permanently resident; if an application continually generates such unreachable groups of unreachable objects this will have the effect of a memory leak. Weak references may be used to solve the problem of circular references if the reference cycles are avoided by using weak references for some of the references within the group.
  • Weak references are also used to minimize the number of unnecessary objects in memory by allowing the program to indicate which objects are not critical by only weakly referencing them.
Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194
Bhushan
  • 18,329
  • 31
  • 104
  • 137
  • 1
    Java (the language given in the tags) is specified not to use reference counting GC. – Bill K Jan 09 '12 at 16:38
  • I think Java GC can use reference counting as one of the strategy, of course it depends on the JVM. Can you give some resource which says that Java cannot use/never uses reference counting? – Bhushan Jan 09 '12 at 16:45
  • 2
    @Brushan The langauge spec demands that cycles be handled correctly, which means that while we can use ref counting, we still have to do a mark&sweep swipe once in a while to break up the cycles. That together with the performance problems of ref counting GCs compared to current concurrent algorithms makes it pretty much uninteresting. – Voo Jan 09 '12 at 18:42
2

I use it generally for some type of cache. Recently accessed items are available immediately and in the case of cache miss you reload the item (DB, FS, whatever).

Jan Zyka
  • 17,460
  • 16
  • 70
  • 118
0

I use WeakSet to encode links in a graph. If a node is deleted, the links automatically disappear.

Neil G
  • 32,138
  • 39
  • 156
  • 257
  • 1
    If my understanding is correct, this is extremely VM dependent. I thought weak references were removed when the GC fired, and didn't contractually oblige the GC to fire. If the GC doesn't fire, the links won't disappear, right? Is this a correctness issue? Do you explicitly call the GC after node deletion? – ccoakley Jan 09 '12 at 18:43
  • @ccoakley: Yes, I call `gc.collect()`. Is that enough to guarantee this works? The edge structure is complicated, and it would be a pain to have to explicitly disconnect things. – Neil G Jan 09 '12 at 18:47
  • I believe your code is conditionally correct, with Sun's JVM. However, the JVM spec (chapter 3) specifies: "...the garbage-collection algorithm used, ... are left to the discretion of the implementor." This means that a (bad) conservative collector might not notice the reference missing and not delete the links at your explicit call to the gc. This is one reason why explicit gc calls are frowned upon; the exact behavior is not exactly platform independent. Take into account that my knowledge is quite limited AND dated on this subject, though. – ccoakley Jan 09 '12 at 19:04
  • 1
    @ccoakley: I'm working in Python, but you're right though: the story is the same. I'll have to fix it at some point. On the bright side, I'm being very conservative with my references in order for this to work, so when I finally do explicitly remove the objects from the dictionaries, I can be sure that there will be no references keeping the link objects alive. – Neil G Jan 09 '12 at 19:12
  • What class is `WeakSet`? I do not find it in Java 10 API. – Basil Bourque Mar 24 '18 at 22:20
  • @BasilBourque Sorry, this was Python. I don't know Java. Anyway, like ccoakley said, it was not a good design. – Neil G Mar 24 '18 at 22:22
  • @NeilG Then I suggest you delete this Answer, if it is irrelevant. – Basil Bourque Mar 24 '18 at 22:22
  • @BasilBourque: It answers the question: "Since weak references can be claimed by the garbage collector at any time, is there any practical reason for using them?" – Neil G Mar 24 '18 at 22:25