The111 The111 - 1 year ago 86
Java Question

JPanel with anonymous EventListener - why doesn't GC destroy listener?

I have been perusing the open source code of JMapViewer. If anyone else wishes to look at it, check the SVN.

In a nutshell, the main class is

, which is an extension of a
. There is another very important class called
which acts as a
for the main class.

The first weird thing I noticed is that the viewer has no references to the controller. The
constructor instantiates an anonymous instance of the
, like this:

public JMapViewer() {
// other stuff
new DefaultMapController(this);

This seems to me to be a poor design choice, since the controller has tons of methods (options, toggles, etc - example shown below), which now can not be accessed at all, so what good are they?

public void setMovementMouseButton(int movementMouseButton) {
// changes which mouse button is used to move the map

The controller does have a reference to the viewer as shown in the first snippet above, which is how it is able to exercise control.

However, then I thought of something even weirder! If this anonymous instance of the listener has no references, why is it allowed to even survive? Shouldn't the GC destroy it quickly? Or is GC smart enough to know that a listener class which references a live
must also stay alive to work properly, even if it has no name for some strange reason?

So, two real questions:

  • why does GC not destroy object?

  • is this indeed a poor design choice, or is there some way I'm unaware of to access the controller from the class which instantiates the viewer?

I want to contribute to this open source library, and my first idea for a change is to change the
class to have a field referencing its controller, and to change the constructor to assign the currently anonymous controller to this new field. But, I want to make sure I'm not ignorantly missing something. I have searched the entire codebase for the text
, and it only occurs in its own class definitions, and in the anonymous instantiations in the


It does indeed appear that there is a way to access the anonymous listeners, by using the
. So technically in my application I could search this collection for instances of
, and use that to access the methods I need to use to change the controller options.

To play devil's advocate though, if I go with original idea and give the map a reference of its controller, now I have a sort of circular reference (map knows of controller and controller knows of map). Is this a bad idea?

Answer Source

The abstract parent, JMapController, holds a reference to the JMapViewer passed there by the DefaultMapController constructor:

public DefaultMapController(JMapViewer map) {

Addendum: The map reference held by the controller is used to (selectively) add up to three controller references to the map's EventListenerList, discussed here. Any one of these would preclude GC. At least one salutary design benefit is that a concrete JMapController need only implement available interfaces.

As suggested in this MVC outline, it would be unusual to give the view a reference to the controller. In contrast, there's nothing wrong with letting the controller register as a listener to the view, as suggested here.

Note that only the no-argument JMapViewer constructor installs a DefaultMapController. You can use the alternate constructor, as noted in comments at line 57-59 in revision 29113 of A complete example is examined here.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download