mdarifmustafa / xswingx

Automatically exported from code.google.com/p/xswingx
0 stars 1 forks source link

MemoryLeak when using PromptSupport.setPrompt(..) #20

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. create many TextFields on a JPanel and call PromptSupport.setPrompt(...) to 
decorate them.
2. remove the JPanel
3. repeat steps one and two several times

What is the expected output? What do you see instead?
I expect that TextFields which I do no longer reference get cleaned up by the 
garbage collector.

What version of the product are you using? On what operating system?
0.2

PromtSupport.setPrompt(..)
calls TextUIWrapper.getDefaultWrapper().install(textComponent, true)
which is actually implemented in AbstractUIChangeHandler as

    private final Set<JComponent> installed = new HashSet<JComponent>();

    public void install(JComponent c){
        if(isInstalled(c)){
            return;
        }

        c.addPropertyChangeListener("UI", this);
        installed.add(c);
    } 

The problem is that if you forget to call uninstall there will be a referece to 
the JComponent even if it is not used anywhere. Which prepevts the object from 
being 

DefaultWrapper extends TextUIWrapper

I see that xswingx is keeping references to my TextFields even if I no longer 
need them. 

I have to manually call TextUIWrapper.getDefaultWrapper().uninstall(...) to 
remove the reference.

Original issue reported on code.google.com by torsten2...@gmail.com on 5 Mar 2012 at 5:09

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. create many TextFields on a JPanel and call PromptSupport.setPrompt(...) to 
decorate them.
2. remove the JPanel
3. repeat steps one and two several times

What is the expected output? What do you see instead?
I expect that TextFields which I do no longer reference get cleaned up by the 
garbage collector.

What version of the product are you using? On what operating system?
0.2

PromtSupport.setPrompt(..)
calls TextUIWrapper.getDefaultWrapper().install(textComponent, true)
which is actually implemented in AbstractUIChangeHandler as

    private final Set<JComponent> installed = new HashSet<JComponent>();

    public void install(JComponent c){
        if(isInstalled(c)){
            return;
        }

        c.addPropertyChangeListener("UI", this);
        installed.add(c);
    } 

The problem is that if you forget to call uninstall there will be a reference 
to the JComponent even if it is not used anywhere. Which prevents garbage 
collection from removing the object.

I suggest to use a WeakHashMap instead of a HashSet. Here is the modified code:

package org.jdesktop.xswingx.plaf;

import java.beans.PropertyChangeListener;
import java.util.Map;
import java.util.WeakHashMap;

import javax.swing.JComponent;

public abstract class AbstractUIChangeHandler implements PropertyChangeListener 
{
    //prevent double installation.
    private final Map<JComponent,Object> installed = new WeakHashMap<JComponent,Object>();

    public void install(JComponent c){
        if(isInstalled(c)){
            return;
        }
        c.addPropertyChangeListener("UI", this);
        installed.put(c,null);
    }

    public boolean isInstalled(JComponent c) {
        return installed.containsKey(c);
    }

    public void uninstall(JComponent c){
        c.removePropertyChangeListener("UI", this);
        installed.remove(c);
    }
}

Original comment by torsten2...@gmail.com on 5 Mar 2012 at 10:00

GoogleCodeExporter commented 8 years ago
in swingx 1.6.2 it is already a WeakHashMap

Original comment by thraw...@gmail.com on 4 May 2012 at 11:17