This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
I am working with an existing custom component that updates itself periodically. The component resides in its own JFrame which can be launched from my main application. The problem I'm having is that the component is not being garbage collected after its window has been closed. I've posted some simple sample code below. This is not the actual code, but it illustrates the issue.
The main class...
The custom component...
In the sample code, a Swing Timer is used to periodically update the label text. I also print out the value of count. But when the secondary frame is closed, the custom component continues to print out the value.
What am I doing wrong? How can I get the component to go out of scope and be garbage collected. What is the best practice for doing this type of thing? I would appreciate any insight. Thanks.
I just ran some tests and saw that a running Timer continues to run even when no longer in scope. Didn't go too deep in the sources, but it's probably still being referenced by the TimerQueue.
I suggest you add a ComponentListener to your custom component and stop() the Timer on componentHidden(...). OF course, after first makng the Timer an instance field instead of local to the constructor.Another approach could be to test the component's isDisplayable() in the Timer's actionPerformed.
There are no new questions, but there may be new answers.
After some more thinking about this, there's yet another approach that gives you finer control over when the Timer is stop()ped. That is to add a public void dispose() method to your CustomLabel that calls timer.stop() and invoke that method from your own code before the reference to the CustomLabel goes out of scope.
Also with reference to your subject line, a Timer wouldn't stop when your references to it go out of scope. Think about it. When a Timer is created with a local variable referencing it, would you expect that Timer to stop firing events when the method in which it was declared returns? Of course not.
Timer#start() adds the timer to the TimerQueue and stop() removes it. So, as long as the timer is running the TimerQueue retains a reference to it and it can be GCed only after being stopped. Read the sources if you're interested in seeing where that's done.
Hope that makes things a little clearer.
Joined: Jul 24, 2006
After looking at the source for javax.swing.Timer, it makes sense to me now. I like the approach of adding a dispose() method. I can easily call it when the window is closed.