In this case, class C is registering a propertyChanged method with a static lis-
tener. Since D is a singleton (and has a long life cycle), it will remain reach-
able. Though the reference to C is removed in main , we have a memory leak.
We can solve this solution in one of three ways.
Solution 1: Explicitly remove the listeners
You can solve this problem by explicitly removing listeners whenever you add
them. With the graphical components, the places for removing listeners are
well defined. The Frame and Dialog classes in the Java AWT library fire the
dispose() method when the associated window is destroyed. Classes that add
listeners and inherit from Frame or Dialog will also want to override the dis-
pose() method and add a call to remove the event listener. For subclasses of
components, cleanup can occur when the component is removed from the
parent's container. This action fires the removeNotify method, which can be
subclassed for the addition of the proper cleanup code. For property change
listeners, the call is removePropertyChangeListener ; for event listeners, the
call is removeActionListener .
For other classes like the one in listing 6.3, there's no logical place. Since
finalize is triggered by garbage collection and we're trying to remove refer-
ences that will inhibit garbage collection, we have to invent a method and call
it when we've finished using the class. It's better to place this code in close
proximity to the code that registers the event listener. Both the add and the
associated remove methods should be commented.
Finally, it's important to periodically verify that addSomeKindOfListener
calls are paired with the associated removeSomeKindOfListener calls. If both
lines are in close proximity, verification is simple. If not, the calls can be paired
with a text search, like grep .
Solution 2: Shorten the life cycle of the anchor
One way to ensure that a listener will be garbage collected is to make sure that
the listener registry can be garbage collected. Listing 6.2 does not have a
memory leak because the registry is a short-lived component. This is usually
not the best solution by itself, because it leaves addActionListener calls