when are components destroyed?

As the docs say, the AWT thread keeps a reference to every created component. This is obvious, as a component doesn't disappear after all user threads have finished. How can I tell the AWT thread to release this reference (to free the component's resources)? Is it enough to call setVisible(false)?

[307 byte] By [Morina] at [2007-9-27 11:23:04]
# 1

No, it is not enough to call setVisible(false). This only hides the display of the component and does not dispose of it in memory. As an example, call setVisible(false) and then call setVisible(true). The component magically reappears without recreating it, because this is only a flag to the paint() method to paint or not paint the component.

The standard way to get rid of a component (or any other class instance) is to set it to null: myclassinstance = null. As long as no other classes have valid references to it, gc will free the memory when it does its thing. Another way to get rid of a particular instance is to set the reference to a new or different instance:

// the first instance is no longer valid at the second call and will be cleaned up

myclassinstance = new MyClassInstance();

... // do nasty things to myclassinstance

myclassinstance = new MyClassInstance();

// first instance loses 'focus' and is no longer valid

myclassinstance = new MyClassInstance();

myotherinstance = new MyClassInstance();

... // do some more nasty stuff

myclassinstance = myotherinstance;

Remember that an instance and a reference are two different things. References are analogous to pointers in C and instances are actual constructed classes residing in memory; references only point to them for access.

Robert Templeton

templer0161a at 2007-7-9 6:01:40 > top of Java-index,Archived Forums,Swing...
# 2

You can't get rid of a component by setting the reference to null. For example:

Frame f = new Frame ();

f.setVisible (true);

f = null;

This does not destroy the component, because the AWT thread still keeps a reference to the component. I want *that* reference to be removed, so the component gets destroyed. There is probably some method in the Component class to do that, or an event that must be sent to the component, but I couldn't find it.

Morina at 2007-7-9 6:01:40 > top of Java-index,Archived Forums,Swing...
# 3
Where did you read that the AWT thread keeps a reference to the component? As far as I know if a component is not referenced it can get garbage collected and there are no 'hidden' references to AWT components.
ricardo_morala at 2007-7-9 6:01:40 > top of Java-index,Archived Forums,Swing...
# 4

I said, and I quote, "As long as no other clas_ses have valid references to it, gc will free the memory when it does its thing." So, you'll need to setVisible(false) and remove() it from the container to which it was add()'d. Then set it to null. Until you set it to null, there is a good chance of it sticking around indefinitely. It is not imperative, but I have found that it gets the attention of the gc() much sooner.

Also, be sure that there are no live objects referencing it, even from below. Dereferencing objects that have complex ties between Java standard objects and your own can be difficult and frustrating, the Frame that you exemplified being one. If your Frame class contains main() for application or init() for applet, killing it could result in termination of your program's execution. In this case, better just to call System.exit(0) (for app). There is also a dispose() method that applies to Frames and Dialogs mainly; this only cleans up the memory used for display, not the objects themselves. A good first step in reclaiming memory.

There is a finalize() method which you may want to use in your classes to see when the objects get tossed in the garbage. This is usually used for personal cleanup before gc, but you can use it to monitor: System.out.println("Frame Msg: I'm getting wiped."); Get the time when the application started, the object was 'supposedly' dereferenced, and subtract from the time of this message and you can track the disparity between object dereference and object expunge (when the gc finally gets to it).

Robert Templeton

templer0161a at 2007-7-9 6:01:40 > top of Java-index,Archived Forums,Swing...
# 5
Also when you remove a component thats no longer used, remember to remove this component from any listener list where it may be registered.
ricardo_morala at 2007-7-9 6:01:40 > top of Java-index,Archived Forums,Swing...
# 6

Hm ...

I wonder, if you must remove all those listeners - think of a JTable, where an AbstractTableModel subclass is used as model - JTable is a listener to the model and it holds a reference to the model - a circular reference.

So my question is: Can this JTable resp. its model be garbage collected if there is no reference to the JTable resp. its model from the application side, but the circular reference as stated above still exists on?

greetings Marsian

marsian27a at 2007-7-9 6:01:40 > top of Java-index,Archived Forums,Swing...
# 7

PLEASE, for now, consider the possibility that I know what a garbage collector is. Please try to run this little program:

-

import java.awt.*;

class test

{

public static void main (String[] args)

{

Frame f = new Frame ();

f.setVisible (true);

f = null;

System.gc ();

}

}

-

No live objects are referencing the frame, at least none that I can see. No listeners, no container, nothing. Still the frame stays on screen. HOW CAN THAT BE? Correct answer, I guess: There must be a hidden reference from some internal AWT object.

In another experiment, I have created a subclass of Frame with overridden finalize() to signal the destruction of the frame. Even after setVisible(false) and setting all references to null, AND calling System.gc(), the object is not destroyed. Objects which are not Components (i.e., I removed the 'extends Frame') are garbage-collected as one would expect.

BTW, marsian27, circular references CAN be handled by the garbage collector. This is one of the main reason why garbage collectors are used (in contrast to reference counting, where circular references prevent proper destruction of the objects).

Morina at 2007-7-9 6:01:40 > top of Java-index,Archived Forums,Swing...
# 8

Hi again,

System.gc() doesn't force the garbage collector to run, it is only a hint and the gc won't normally start if there is enough memory left, regardless how often you call System.gc().

To JFrames, which are shown on the screen: I often create frames without holding a reference to them with the dispose-on-close or exit-on-close option. They definitely are there as long as they are not closed and will not be finalized during they are not closed, even so the garbage collector is running and there is no reference to this frame in my application. So, I guess, there must be a kind of internal reference to this frame which prevents it from being finalized and garbage collected.

@Morin: Yes, I hoped so, that circular references can be handled by the garbage collector, even so I haven't tested it - but I am glad to hear, that it is definitely so.

greetings Marsian

marsian27a at 2007-7-9 6:01:40 > top of Java-index,Archived Forums,Swing...
# 9

I've found the solution: dispose() is the method I was looking for. I first overlooked it since the docs are unclear about the effect of this method: dispose() doesn't only free the native screen resources (as the docs say), but also releases the internal reference to the frame. setVisible(false) alone is not enough.

Morina at 2007-7-9 6:01:40 > top of Java-index,Archived Forums,Swing...
# 10

Thats the correct answer. When you remove a component from a container it is not necessary to call dispose because the removeNotify method of Component (called when the component is removed) will call it for you. But if you want to dispose a Window you must call it by hand. The javadoc of the dispose method of Windows says:

* 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.

*

* The Window and its subcomponents can be made displayable again

* by rebuilding the native resources with a subsequent call to

* pack or show. The states of the recreated

* Window and its subcomponents will be identical to the states of these

* objects at the point where the Window was disposed (not accounting for

* additional modifcations between those actions).

bye.

ricardo_morala at 2007-7-9 6:01:40 > top of Java-index,Archived Forums,Swing...