How do I get AppContext to release AWT components so they can be garbage collected?
My team is working on analyzing our Swing application to make sure everything is being garbage collected when it's no longer being used. We're running into an odd problem.
We are simply opening a new window (JFrame
) and closing it. This frame contains an EmptyPanel
class (which contains a short message saying there is no data) and a custom JMeunBar
class. We don't interact with this at all - just close the window immediately.
Then, we force a garbage collection and do a heap dump.
Upon analysis of the heap dump, the JMenuBar
isn't being garbage collected. It's being kept open from the GC Root sun.awt.AppContext
.
How do we clean this up? Or is this something we don't have to worry about for some reason? We want to be diligent making sure our application cleans up after itself, but we don't want to spin our wheels on this either.
AppContext.mainAppContext
contains a HashMap which contains a BasicPopupMenuUI.MenuKeyboardHelper
instance. Inside this is a ComponentInputMapUIResource.menuInputMap
which has this JMenuBar
as a component.
Solution 1:
As discussed here there are a number of system resources that must be freed explicitly in the normal course of the JVM's operation. The graphics context's dispose()
method is one example; the parent window's dispose()
method is another. In either, the resource may be correctly released, but you may observe the heap before it has been finalized.
It's hard to generalize about what can be safely ignored, but one empirical approach is to exercise the target in a profiler. The first two graphs in this comparison show a small but steady increase in memory consumed by a certain method that is suspected of retaining resources. In contrast, the third chart shows flat memory use with periodic spikes of garbage collection activity. Below is the typical saw-tooth pattern of a visually "busy" program such as this game. Note that each cycle returns to the baseline.