Skip to main content

Memory leak question

17 replies [Last post]
carcour
Offline
Joined: 2003-06-18

Hi,
Looking at the following code are removeWindowListener(wa) and remove(tf) necessary so that the JFrame will be GC'ed after it has been disposed or not? From what I have read on the net yes but there's nothing in the Java Tutorial that talks about that maybe it should be added to the tutorial so people will know how to write correct Swing code.
Thanks in advance,

Carl Antaki

<br />
import java.awt.FlowLayout;<br />
import java.awt.event.ActionEvent;<br />
import java.awt.event.ActionListener;<br />
import java.awt.event.WindowAdapter;<br />
import java.awt.event.WindowEvent;</p>
<p>import javax.swing.JButton;<br />
import javax.swing.JFrame;<br />
import javax.swing.JTextField;<br />
import javax.swing.SwingUtilities;</p>
<p>/**<br />
 * Created on 15-May-07<br />
 *<br />
 *@author Carl Antaki<br />
 *<br />
 */</p>
<p>public class TestFrame extends JFrame {<br />
    private JButton b ;<br />
    TestFrame(){<br />
        setLayout(new FlowLayout());<br />
        b = new JButton("click");<br />
        b.addActionListener(new ActionListener(){<br />
            public void actionPerformed(ActionEvent e) {<br />
                new ChildFrame();<br />
            }<br />
        });<br />
        add(b);</p>
<p>        pack();<br />
        setLocationRelativeTo(null);<br />
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
        setTitle("TestFrame leak");<br />
        setVisible(true);<br />
    }<br />
    public static void main(String[] args) {<br />
        SwingUtilities.invokeLater(new Runnable() {<br />
            public void run() {<br />
                createAndShowGUI();<br />
            }<br />
        });<br />
    }</p>
<p>    private static void createAndShowGUI(){<br />
        new TestFrame();<br />
    }<br />
}</p>
<p>class ChildFrame extends JFrame{<br />
    JTextField tf;<br />
    WindowAdapter wa ;<br />
    ChildFrame(){<br />
        tf = new JTextField("Hi");<br />
        wa = new WindowAdapter(){<br />
            @Override<br />
            public void windowClosing(WindowEvent e) {<br />
                setVisible(false);<br />
                removeWindowListener(wa);<br />
                remove(tf);<br />
                dispose();</p>
<p>            }<br />
        };<br />
        addWindowListener(wa);<br />
        add(tf);<br />
        pack();<br />
        setLocationRelativeTo(null);<br />
        setVisible(true);<br />
    }<br />
}<br />

Message was edited by: carcour

Message was edited by: carcour

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
naks
Offline
Joined: 2007-11-07

Hi Kirillcool,

In our project we are facing a memory leakage issue. Memory is getting leaked in Frame. In the frame we have lots of listeners(Action listeners for all buttons and window listener for the frame.). After closing the frame the memory is not getting deallocated.

In the following link i observed that JFrame on closing it will not free the memory allocated to it.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6257260

In our application we are using JDK1.5.0_10.

If you have any information regarding this please let me know.

finganni1
Offline
Joined: 2005-12-29

Hi carcour,
seems to me that the example given in the article from Oracle depicts a situation where the addMyListener method call means somehow creating within MyListener() a reference to the object [i]object[/i], therefore if You want the object [i]object[/i] to be GCable You must remove its reference from MyListener() (that's why removeMyListener is mandatory).

Well, this is right the opposite relationship the addWindowListener method creates.
When You add Your window adapter (and Kiricool has made perfectly clear is not necessary at all) to a frame You are actually creating a reference to the adapter (not the frame) which will be notified when the frame is disposed. So no any new strong reference to the frame is created and disposing the frame makes it eligible for GC and therefore no memory leak should occur in the code You provided as an example even if You do not remove the window adapter or the component.
Moreover both adapter and UI components added to the frame will be GCed as well.

Rgds

naks
Offline
Joined: 2007-11-07

Hi all,

In our project we are facing a memory leakage issue. Memory is getting leaked in Frame. In the frame we have lots of listeners(Action listeners for all buttons and window listener for the frame.). After closing the frame the memory is not getting deallocated.

In the following link i observed that JFrame on closing it will not free the memory allocated to it.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6257260

In our application we are using JDK1.5.0_10.

If you have any information regarding this please let me know.

kirillcool
Offline
Joined: 2004-11-17

Why all this trouble if you want to dispose the frame? Call setDefaultCloseOperation with DISPOSE_ON_CLOSE.

carcour
Offline
Joined: 2003-06-18

I know [i]setDefaultCloseOperation [/i]but what I'm saying is that I was wondering if not removing listeners will cause memory leaks (the JFrame won't be GC'ed) so I had to use a WindowAdapter instead.

kirillcool
Offline
Joined: 2004-11-17

You don't need to register the WindowAdapter to dispose the frame on close button click. The DISPOSE_ON_CLOSE will do it for you. Do you actually have a memory leak or not (before going and updating Swing tutorials with a listener that unregisters itself from inside event handler code, not to mention that a disposed frame can be re-show()'d and your listener will be gone by then, meaning that the second time you won't be able to dispose the frame)?

carcour
Offline
Joined: 2003-06-18

Look at this http://www.oracle.com/technology/pub/articles/masterj2ee/j2ee_wk11.html
"In practice, registering a listener includes adding a reference from the listener to the object. Listener registration is achieved through a call like this:

object.addMyListener(new MyListener(...));

It is important to remove this reference with a matching call to

object.removeMyListener(l);

thus unregistering the listener and allowing object to be garbage-collected. "

kirillcool
Offline
Joined: 2004-11-17

What does this have to do with what i wrote? You don't need a listener to dispose a frame on close button click, the next time the frame will be shown, it won't have the listener since you unregistered it (thus making the frame undisposable), *and* you're unregistering the listener in the same event that triggered it.

carcour
Offline
Joined: 2003-06-18

My only question is do I need to manually remove listeners from components and components from panels so that the JFrame will be GC'ed?
My aim is to have a correct answer from a Swing Engineer or a Swing guru.

Message was edited by: carcour

kirillcool
Offline
Joined: 2004-11-17

Yes you do.

However, the example that you have provided is not a good one, and has many problems with it.

carcour
Offline
Joined: 2003-06-18

Thanks for the answer but could you provide more details in what is wrong in the code I provided.
Thanks in advance,

Carl

kirillcool
Offline
Joined: 2004-11-17

Reread my replies, they list at least three problems in your code.

carcour
Offline
Joined: 2003-06-18

Hi Kirill,
I don't think you're being very clear. First you tell me I can just use [i]DISPOSE_ON_CLOSE[/i]
and then you agree to say that I need to remove components from the content pane and unregister listeners from the components. What is your final answer?
Look at that: http://mindprod.com/jgloss/packratting.html
From what I understand DISPOSE_ON_CLOSE will dispose the native peers, JFrame being a heavy weight component will be disposed but we need to remove the references to the other lightweight objects so there won't be any JTextField objects in memory for example in my case. http://www.ddj.com/dept/java/184404011
Thanks.
Carl

kirillcool
Offline
Joined: 2004-11-17

Have you actually tried to run this example through a profiler to see if DISPOSE_ON_CLOSE results in memory leaks (without explicitly removing the children)? And, if you use DISPOSE_ON_CLOSE, you don't need a WindowAdapter, so there's no listener to unregister.

You do need to unregister all the listeners that you register, but in this specific example you don't need to register one in the first place.

About the child component - i didn't say that you need to remove them. If your frame is the only one referencing them, and the frame doesn't have any strong reference, it is subject to GC with all its child components (unless a UI delegate for some child component holds a reference to it in some static data structure). The same would be true for a map that is not referenced any longer - you don't need to explicitly clear it out.

carcour
Offline
Joined: 2003-06-18

I have used Rational JPurify and I noticed that it leaked 24B every time I opened the frame. The measurement was done correctly I open the JFrame then close it I garbage collect using the tool then I reopen and I compare both snapshots. I've tried Netbeans profiler but it didn't show any leaks but Netbeans doesn't give a lot of details. Kirill I know that using DISPOSE_ON_CLOSE doesn't require a WindowAdapter it's not the first Swing application I'm writing :) This was just a sample application for testing purposes. By strong reference do you mean not a weak or soft reference?
Btw Substance is very cool. Keep up the good work.

kirillcool
Offline
Joined: 2004-11-17

I'd say that a frame or even a text field will take much more than 24 bytes - or is it supposed to be 24KB? Any decent profiler can take a snapshot of the heap, filter out objects that can be garbage collected and then show paths to the GC roots. Then, you can see who exactly is holding a strong reference to that frame that can not be garbage collected. It might be some UI delegate tracking something in a static map, or some other internal Swing class doing something it's not supposed to.

carcour
Offline
Joined: 2003-06-18

It's 24 bytes. Maybe I'm using the wrong profiler because it doesn't give me the paths.
I was reading this http://www-128.ibm.com/developerworks/rational/library/1499.html that's why I wanted to remove listeners from the JFrame.