Context
Wanting to learn how to use custom JDialogs for non-trivial, validated data input, I searched and found an interesting answer to a closely related question.
What I don't understand is why the code in the provided answer works.
My Question
Since the JDialog object has executed setVisible(false) and dispose() in the actionPerformed() method of its anonymous ActionListener, by the time the caller gets back program flow and tries to get the fields, shouldn't the Garbage Collector have destroyed this fields already?
dispose will only dispose of the native peer resources held by the dialog. If you still have a reference to the JDialog in question, it won't be eligible for garbage collection since you still have a strong reference to it. I assuming you still have a reference to the dialog, because otherwise, how else would you be trying to get the values managed by it...
Also garbage collection doesn't happen straight away...
Based on your linked question...
FObjectDialog fod = new FObjectDialog(this);
//...
String name = fod.getName();
There's still a strong reference to FObjectDialog through fod. So, until either fod goes out of the context (the method returns), is dereferenced (fod = null;) or is reassigned, fod (and the dialog by extension) won't be eligible for garbage collection.
After wondering whether disposing my frame would return a null (if checked) I went ahead and tested it out. I've searched on dispose() but most of the articles I read just state when to use it, not what it actually does. I tried out the sample code, maybe my code is simply incorrect but if it's not. What does dispose() actually do inside the JVM?
If someone does find a link related to this, please post it so I can remove this question
Objects can change their state. However, they cannot willy-nilly change any state in the entire collection of other objects.
So, if you call any method on an object, it will not have a direct impact on any reference to that object from any possible other object.
In your case, dispose() is releasing the in-object references to the wrapped OS level components, not removing the Java object from the environment (and clearing out its references).
1) No method ever can set your variable to null. Never ever. It may change an internal state so any future call may throw an error (e.g. with a Socket), but the variable itself won't be changed. You need to do this explicitly yourself.
2) Read the javadocs :)
Releases all of the native screen resources used by this Window, its subcomponents, and all of its owned children. That is, the resources for these Components will be destroyed, any memory they consume will be returned to the OS, and they will be marked as undisplayable.
[...]
What are the pros and cons of keeping listeners as WeakReferences?
The big 'Pro' of course is that:
Adding a listener as a WeakReference means the listener doesn't need to bother 'removing' itself.
For those worried about the listener having the only reference to the object, why can't there be 2 methods, addListener() and addWeakRefListener()?
Those who don't care about removal can use the latter.
First of all, using WeakReference in listeners lists will give your object different semantic, then using hard references. In hard-reference case addListener(...) means "notify supplied object about specific event(s) until I stop it explicitly with removeListener(..)", in weak-reference case it means "notify supplied object about specific event(s) until this object will not be used by anybody else (or explicitly stop with removeListener)". Notice, it is perfectly legal in many situations to have object, listening for some events, and having no other references keeping it from GC. Logger can be an example.
As you can see, using WeakReference not just solve one problem ("I should keep in mind to not forget to remove added listener somewhere"), but also rise another -- "I should keep in mind that my listener can stop listen at any moment when there is no reference to it anymore". You not solve problem, you just trade one problem for another. Look, in any way you've forced to clearly define, design and trace livespan of you listener -- one way or another.
So, personally, I agree with mention what use WeakReference in listeners lists is more like a hack than a solution. It's pattern worth to know about, sometimes it can help you -- to make legacy code work well, for example. But it is not pattern of choice :)
P.S. Also it should be noted what WeakReference introduce additional level of indirection, which, in some cases with extremely high event rates, can reduce performance.
This is not a complete answer, but the very strength you cite can also be its principal weakness. Consider what would happen if action listeners were implemented weakly:
button.addActionListener(new ActionListener() {
// blah
});
That action listener is going to get garbage collected at any moment! It's not uncommon that the only reference to an anonymous class is the event to which you are adding it.
I have seen tons of code where listeners were not unregistered properly. This means they were still called unnecessarily to perform unnecessary tasks.
If only one class is relying on a listener, then it is easy to clean, but what happens when 25 classes rely on it? It becomes much trickier to unregister them properly. The fact is, your code can start with one object referencing your listener and end up in a future version with 25 objects referencing that same listener.
Not using WeakReference is equivalent to taking a big risk of consuming unnecessary memory and CPU. It is more complicated, trickier and requires more work with hard references in the complex code.
WeakReferences are full of pros, because they are cleaned up automatically. The only con is that you must not forget to keep a hard reference elsewhere in your code. Typically, that would in objects relying on this listener.
I hate code creating anonymous class instances of listeners (as mentioned by Kirk Woll), because once registered, you can't unregister these listeners anymore. You don't have a reference to them. It is really bad coding IMHO.
You can also null a reference to a listener when you don't need it anymore. You don't need to worry about it anymore.
There are really no pros. A weakrefrence is usually used for "optional" data, such as a cache where you don't want to prevent garbage collection. You don't want your listener garbage collected, you want it to keep listening.
Update:
Ok, I think I might have figured out what you are getting at. If you are adding short-lived listeners to long-lived objects there may be benefit in using a weakReference. So for example, if you were adding PropertyChangeListeners to your domain objects to update the state of the GUI that is constantly being recreated, the domain objects are going to hold on to the GUIs, which could build up. Think of a big popup dialog that is constantly being recreated, with a listener reference back to an Employee object via a PropertyChangeListener. Correct me if I'm wrong, but I don't think the whole PropertyChangeListener pattern is very popular anymore.
On the other hand, if you are talking about listeners between GUI elements or having domain objects listening to GUI elements, you won't be buying anything, since when the GUI goes away, so will the listeners.
Here are a couple interesting reads:
http://www.javalobby.org/java/forums/t19468.html
How to resolve swing listener memory leaks?
To be honest I don't really buy that idea and exactly what you expect to do with a addWeakListener. Maybe it is just me, but it appear to be a wrong good idea. At first it is seducing but the problems it might implies are not negligible.
With weakReference you are not sure that the listener will no longer be called when the listener itself is no longer referenced. The garbage collector can free up menmory a few ms later or never. This mean that it might continue to consume CPU and make strange this like throwing exception because the listener shall not be called.
An example with swing would be to try to do things you can only do if your UI component is actually attached to an active window. This could throw an exception, and affect the notifier making it to crash and preventing valid listeners to be notofied.
Second problem as already stated is anonymous listener, they could be freed too soon never notified at all or only a few times.
What you are trying to achieve is dangerous as you cannot control anymore when you stop receiving notifications. They may last for ever or stop too soon.
Because you are adding WeakReference listener, I'm assuming, you are using a custom Observable object.
It makes perfect sense to use a WeakReference to an object in the following situation.
- There is a list of listeners in Observable object.
- You already have a hard reference to the listeners somewhere else. (you'd have to be sure of this)
- You don't want the garbage collector to stop clearing the listeners just because there is a reference to it in the Observable.
- During garbage collection the listeners will be cleared up. In the method where you notify the listeners, you clear up the WeakReference objects from the notification list.
In my opinion it's a good idea in most cases. The code that is responsible for releasing the listener is at the same place where it gets registered.
In practice i see a lot of software which is keeping listeners forever. Often programmers are not even aware that they should unregister them.
It usually is possible to return a custom object with a reference to the listener that allows manipulation of when to unregister. For example:
listeners.on("change", new Runnable() {
public void run() {
System.out.println("hello!");
}
}).keepFor(someInstance).keepFor(otherInstance);
this code would register the listener, return an object that encapsulates the listener and has a method, keepFor that adds the listener to a static weakHashMap with the instance parameter as the key. That would guarantee that the listener is registered at least as long as someInstance and otherInstance are not garbage collected.
There can be other methods like keepForever() or keepUntilCalled(5) or keepUntil(DateTime.now().plusSeconds(5)) or unregisterNow().
Default can be keep forever (until unregistered).
This could also be implemented without weak references but phantom references that trigger the removal of the listener.
edit: created a small lib which implements a basic version of this aproach https://github.com/creichlin/struwwel
I can't think of any legitimate use case for using WeakReferences for listeners, unless somehow your use case involves listeners that explicitly shouldn't exist after the next GC cycle (that use case, of course, would be VM/platform specific).
It's possible to envision a slightly more legitimate use case for SoftReferences, where the listeners are optional, but take up a lot of heap and should be the first to go when free heap size starts getting dicey. Some sort of optional caching or other type of assisting listener, I suppose, could be a candidate. Even then it seems like you'd want the internals of the listeners to utilize the SoftReferences, not the link between the listener and listenee.
Generally if you're using a persistent listener pattern, though, the listeners are non-optional, so asking this question may be a symptom that you need to reconsider your architecture.
Is this an academic question, or do you have a practical situation you're trying to address? If it's a practical situation I'd love to hear what it is -- and you could probably get more, less abstract advice on how to solve it.
I have 3 suggestions for the original poster. Sorry for resurrecting an old thread but I think my solutions were not previously discussed in this thread.
First,
Consider following the example of javafx.beans.values.WeakChangeListener in the JavaFX libraries.
Second,
I one upped the JavaFX pattern by modifying the addListener methods of my Observable. The new addListener() method now creates instances of the corresponding WeakXxxListener classes for me.
The "fire event" method was easily modified to dereference the XxxWeakListeners and to remove them when the WeakReference.get() returned null.
The remove method was now a bit nastier since I need to iterate the entire list, and that means I need to do synchronization.
Third,
Prior to implementing this strategy I employed a different method which you may find useful. The (hard reference) listeners got a new event they did a reality check of whether or not they were still being used. If not, then they unsubscribed from the observer which allowed them to be GCed. For short lived Listeners subscribed to long lived Observables, detecting obsolescence was fairly easy.
In deference to the folks who stipulated that it was "good programming practice to always unsubscribe your listeners, whenever a Listener resorted to unsubscribing itself, I made sure to create a log entry and corrected the problem in my code later.
WeakListeners are useful in situations where you specifically want GC to control the lifetime of the listener.
As stated before, this really is different semantics, compared to the usual addListener/removeListener case, but it is valid in some scenarios.
For example, consider a very large tree, which is sparse - some levels of nodes are not explicitly defined, but can be inferred from parent nodes further up the hierarchy. The implicitly defined nodes listen to those parent nodes that are defined so they keep their implied/inherited value up to date. But, the tree is huge - we don't want implied nodes to be around forever - just as long as they are used by the calling code, plus perhaps a LRU cache of a few seconds to avoid churning the same values over and over.
Here, the weak listener makes it possible for child nodes to listen to parents while also having their lifetime decided by reachability/caching so the structure doesn't maintain all the implied nodes in memory.
You may also need to implement your listener with a WeakReference if you are unregistering it somewhere that isn't guaranteed to be called every time.
I seem to recall we had some problems with one of our custom PropertyChangeSupport listeners that was used inside row Views in our ListView. We couldn't find a nice and reliable way to unregister those listeners, so using a WeakReference listener seemed the cleanest solution.
It appears from a test program that anonymous ActionListeners will not prevent an object from being garbage collected:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
public class ListenerGC {
private static ActionListener al = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.err.println("blah blah");
}
};
public static void main(String[] args) throws InterruptedException {
{
NoisyButton sec = new NoisyButton("second");
sec.addActionListener(al);
new NoisyButton("first");
//sec.removeActionListener(al);
sec = null;
}
System.out.println("start collect");
System.gc( );
System.out.println("end collect");
Thread.sleep(1000);
System.out.println("end program");
}
private static class NoisyButton extends JButton {
private static final long serialVersionUID = 1L;
private final String name;
public NoisyButton(String name) {
super();
this.name = name;
}
#Override
protected void finalize() throws Throwable {
System.out.println(name + " finalized");
super.finalize();
}
}
}
produces:
start collect
end collect
first finalized
second finalized
end program
It depends on what you want to do.
If you want to create a reactive value that depends on a specific value but where the callback is not supposed to have side effects, use a weak reference.
If you want to set up a callback which is run for its side effects, use a strong reference.
Imho, this is also why I strongly feel that the observer pattern should be encapsulated into a library most times, with something like Signal/ComputedSignal/Effect and the like.
Your register methods should be named based on what you want to do. The case where you want a reactive dependent value should be something like Subject.dependent_value( (args) => value) while the case with the Effect should be Subject.register_effect((args) => dostuff...).
Effects that depend on dependent values should walk their dependency graphs and register themselves as a strong child of the root observables.
Is it possible to create an object which will be alive till the JVM is not shut down? Or is there any java objects which remains alive till the JVM is not shutdown.
You can be fairly certain that a static field will not be garbage collected. See this question for details.
The main Thread of your program is always alive until the JVM shuts down.
Why are you asking this question ?
Every JVM instance has only one java.lang.Runtime instance. Created at the start and stays till the end. If you want everlasting then there are two ways:
Override protected void finalize() throws Throwable; and Self reference the object in it.
Maintain reference to your object
Of course. All you have to do is make sure the object is reachable by running code, and it won't die. The GC only collects stuff that the code doesn't have a reference to anymore.
A single static reference (that you never set to null) within one of your classes should be enough to guarantee that the object sticks around as long as the app is running. However, as long as you are able to see and use the object, it should stick around anyway. (There's a concept called "weak references" that makes this not always true, but if you're using them, then you wouldn't be asking the question.)
I'm having problem with some framework API calling BufferedImage.getGraphics() method and thus causing memory leak. What this method does is that it always calls BufferedImage.createGraphics(). On a windows machine, createGraphics() is handled by Win32GraphicsEnvironment which keeps a listeners list inside its field displayChanger. When I call getGraphics on my BufferedImage someChart, someChart's SurfaceManager(which retains a reference to someChart) is added to the listeners map in Win32GraphicsEnvironment, preventing someChart to be garbage collected. Nothing afterwards removes someChart's SurfaceManager from the listeners map.
In general, the summarized path stopping a BufferedImage from being garbage collected, once getGraphics is called, is as follows:
GC Root -> localGraphicsEnvironment(Win32GraphicsEnvironment)
-> displayChanger(SunDisplayChanger) -> listeners(Map) -> key(D3DChachingSurfaceManager) -> bImg(BufferedImage)
I could have changed the framework's code so that after every called to BufferedImage.getGraphics(), I keep a reference to the BufferedImage's SurfaceManager. Then, I get hold of localGraphicsEnvironment, cast it to Win32GraphicsEnvironment, then call removeDisplayChangedListener() using the reference to the BufferedImage's SurfaceManager. But I don't think this is a proper way to solve the problem.
Could someone please help me with this issue? Thanks a lot!
MORE DETAILS AND FINDINGS
The component I'm trying to add to my UI is makes calls to BufferedImage.getGraphics() every time it is repainted. As a result, the number of garbage kept by displayChanger(inside SunGraphicsEnvironment) should grow as the component gets repainted.
However, things a behaving weirdly enough:
when I counted my actions on my UI which would surely trigger repaint, then check the number of garbage listeners inside displayChanger against my count, they don't match up. (eg. There were 8 listeners before my clicks, and I made 60 clicks. After all, there are only 18 listeners.)
On the other hand, if I turn on the breakpoint, and step into the process of adding things to displayListeners, every single click resulted in a new entry in displayListeners. And thus, every BufferedImage held by displayListeners become garbage.
I considered the possibility of SurfaceManager, which is used as the key for displayListeners, may be shared or reused, yet my experiment ruled out this possibility. I also considered caching and I deliberately prevented caching from happening by making every call to repaint unique. Still, I have no clue how this could happen and how to solve the leak.
After rendering the BufferedImage, you should invoke dispose() on the graphics context returned by createGraphics(). Here's an example and a list of similar methods.
Addendum: This seems like an object leak called packratting; the listener mismatch sounds like an artifact of using the debugger. You might get some ideas from the article Plugging memory leaks with soft references, by Brian Goetz.
Try to call flush() when you don't need your image any more.