I have a Java application that loads an image with Toolkit.getImage(). Even if I flush() the image and set the Image object
to null, the Java DOS window doesn't close. Is this because something is still being referenced?
The DOS window closes when the application ends (i.e., when the Java virtual machine exits). Keeping references to objects
won't prevent the application from ending. There are two ways for the Java virtual machine to exit:
System.exit or by calling exit on the runtime
The first case requires further explanation. The definition of a daemon thread is circular in this discussion. A thread should
be made a daemon thread when you don't want that thread alone to keep the program alive. When a thread is created, it can
be marked as a daemon thread with a call to setDaemon(true). (Note that this must be called before the start method.) A thread created from another daemon thread is a daemon thread by default. In most programs with no GUI and no threads
created by the developer, the "main" thread is the only non-daemon thread. The program will therefore end when main completes.
So, why does the call to Toolkit.getImage() prevent the program from ending? To explain this, let's see what threads are running. For this test, we use Sun's JDK 1.1.7.
Note that some details are implementation-dependent and may vary across ports, but the concepts are the same. On Windows,
a full thread dump will be printed out if you hit CTRL-Break in the command prompt in which the Java program is running. On
Solaris, you can send the kill -QUIT signal to the Java process, or hit CTRL-\ in the Java window. (Note: CTRL-\ may not be mapped to kill -QUIT on all setups.) Doing this reveals two possibly unexpected threads:
AWT-EventQueue-0AWT-Windows/AWT-MotifBoth are non-daemon threads and therefore cause the Java virtual machine to stay alive. Creating the Toolkit caused the appropriate threads for dealing with native windows and user input to be created. Once created, they won't end
on their own.
Is this correct? Some would argue that these threads should be created as daemon threads. But it isn't that simple. Many applications
simply create and show a GUI in main and they wouldn't expect the program to end at this point. Could the AWT somehow be more intelligent, e.g., able to consider
when there are no longer any visible frames? Possibly, but this is a complicated issue to deal with generically, and that
isn't how Sun decided to implement it. Therefore, once the AWT threads are started, you must call System.exit to end the program when appropriate for the given application.
On a side note, System.exit doesn't work on applets, and calling it will cause a SecurityException to be thrown. The lifecycle of an applet is handled by the browser and may vary slightly in different implementations.