Your JFrame default close action can be set to “DISPOSE_ON_CLOSE
” instead of EXIT_ON_CLOSE
(why people keep using EXIT_ON_CLOSE is beyond me).
If you have any undisposed windows or non-daemon threads, your application will not terminate. This should be considered a error (and solving it with System.exit is a very bad idea).
The most common culprits are java.util.Timer and a custom Thread you’ve created. Both should be set to daemon or must be explicitly killed.
If you want to check for all active frames, you can use Frame.getFrames()
. If all Windows/Frames are disposed of, then use a debugger to check for any non-daemon threads that are still running.