简体   繁体   中英

Java Memory Leak Issue with JPanels

Java Memory Leak

private boolean refreshResponseWindow(MessageObject message) {
  this.responsePanel.removeAll();
  this.responsePanel.add(message.buildGUI());
  this.responsePanel.validate();
  message = null;
  return true;

}

The problem that is occurring is as I receive more and more messages my Java program's memory usage continues to grow eventually causing it to lock up. I've isolated my memory leak to the code above specifically the add procedure call. I'd assume the removeAll would clear the contents of my panel but it still seems to continue to grow.

Note: The message.buildGUI() returns a JPanel that is displayed on the responsePanel

Follow up:

The BuildGUI code appears as such

public JPanel buildGUI() throws Exception {
    JPanel busPanel = new JPanel();
    busPanel.setLayout(new GridBagLayout());
    busPanel.setPreferredSize(new Dimension(Globals.panelW, Globals.panelH));
    busPanel.setMinimumSize(new Dimension(Globals.panelW, Globals.panelH));

    final JLabel headingLabel = new JLabel();
    headingLabel.setFont(new Font("", Font.PLAIN, 18));
    headingLabel.setText(this.name);
    final GridBagConstraints gridBagConstraints_heading = new GridBagConstraints();
    gridBagConstraints_heading.gridwidth = 2;
    gridBagConstraints_heading.gridy = 0;
    gridBagConstraints_heading.gridx = 0;
    busPanel.add(headingLabel, gridBagConstraints_heading);
    //Many more gui components marked as final
    return busPanel;

There are no listeners the returned panel is for display purposes only.

Does the buildGUI method add listeners to your business objects? That's a common source of memory leaks. Calling responsePanel.removeAll() will remove the components, but the components may still be registered as listeners on the responsePanel or other objects, causing them to be retained in memory.

Here is solution to the removeAll() memory leak issue... 解决的removeAll()内存泄漏问题...
I call it component annihilation.

It's not very efficient and I wouldn't recommend using it unless you really need to.
It can be sped up by specifying listener types to look for.

Note: It removes the LayoutManager from the panel so you need to re-add it.

Examples of Use:


Utils.annihilateComponent(myJPanel,null,null); // This is slow if myJPanel has many components
myJpanel.setLayout(new FlowLayout());

Utils.annihilateComponent(myJPanel,new String[]{"Action","Mouse","PopupMenu"},new String[]{"java.awt.event.","javax.swing.event."});
myJPanel.setLayout(new MigLayout());
myJPanel.add(new JLabel("Once you start using MigLayout you'll never look back"),"wrap");

//In an JDialog:
private void formWindowClosing(java.awt.event.WindowEvent evt) {
    Utils.annihilateComponent(this);
}

Here's the Code:


import java.awt.*;
import java.lang.reflect.Method;
import java.util.EventListener;

public class Utils {
    private static String[] allPackages = { "java.awt.event.","javax.swing.event.","java.beans.","java.beans.beancontext."
            ,"java.awt.dnd.","javax.sql.","javax.naming.event.","javax.imageio.event.","javax.net.ssl.","javax.sound.midi."
            ,"javax.naming.ldap.","java.util.prefs.","javax.sound.sampled." };
    public static void removeListeners (Object o, String listenerName, String[] packages) {
        Class oc = o.getClass();
        try {
            Method getListenersMethod = oc.getMethod("get"+listenerName+"Listeners",(Class[])null);
            String[] p;
            if (packages == null) {
                p = allPackages;
            } else {
                p = packages;
            }

            // Find the listener Class
            Class listenerClass = null;
            int pIndex = 0;
            while (listenerClass == null && pIndex < p.length) {
                try {
                    listenerClass = Class.forName(p[pIndex]+listenerName+"Listener");
                } catch (Exception ex) {
                    /* Ignore */
                }
                pIndex++;
            }
            if (listenerClass == null) {
                return; // Couldn't find the class for this listener type
            }

            Method removeListenerMethod = oc.getMethod("remove"+listenerName+"Listener", new Class[] { listenerClass });
            if (getListenersMethod != null) {
                    //res1 = m.invoke(dto1,(Object[])null);

                Object els = getListenersMethod.invoke(o,(Object[])null);
                if (els instanceof EventListener[]) {
                    EventListener[] listeners = (EventListener[])els;
                    for (int i = 0; i < listeners.length; i++) {
                        removeListenerMethod.invoke(o, new Object[] { listeners[i] });
                    }
                }
            }
        } catch (Exception e) {
            // Ignore
        }
    }

    private static String[] allListeners = { "Action","Adjustment","Ancestor","AWTEvent","BeanContextMembership","BeanContextServiceRevoked"
            ,"BeanContextServices","Caret","CellEditor","Change","Component","ConnectionEvent","Container","ControllerEvent"
            ,"Document","DragGesture","DragSource","DragSourceMotion","DropTarget","Focus","HandshakeCompleted","HierarchyBounds"
            ,"Hierarchy","Hyperlink","IIOReadProgress","IIOReadUpdate","IIOReadWarning","IIOWriteProgress","IIOWriteWarning"
            ,"InputMethod","InternalFrame","Item","Key","Line","ListData","ListSelection","MenuDragMouse","MenuKey","Menu"
            ,"MetaEvent","MouseInput","Mouse","MouseMotion","MouseWheel","NamespaceChange","Naming","NodeChange","ObjectChange"
            ,"PopupMenu","PreferenceChange","PropertyChange","RowSet","SSLSessionBinding","TableColumnModel","TableModel"
            ,"Text","TreeExpansion","TreeModel","TreeSelection","TreeWillExpand","UndoableEdit","UnsolicitedNotification"
            ,"VetoableChange","WindowFocus","Window","WindowState" } ;

    public static void removeAllListeners(Component c, String[] listeners, String[] packages) {
        String[] l;
        if (listeners == null) {
            l = allListeners;
        } else {
            l = listeners;
        }
        for (int i = 0; i < l.length; i++) {
            removeListeners(c,l[i],packages);
        }
    }

    public static void annihilateComponent(Object o, String[] listeners, String[] packages) {
        if (o == null) {
            return;
        }
        if (o instanceof Container) {
            Component[] c = ((Container)o).getComponents();
            for (int i = 0; i < c.length; i++) {
                annihilateComponent(c[i],listeners,packages);
            }
            ((Container)o).setLayout(null);
            ((Container)o).setFocusTraversalPolicy(null);
            ((Container)o).removeAll();
        }
        if (o instanceof javax.swing.JScrollPane) {
            ((javax.swing.JScrollPane)o).setViewportView(null);
        }
        if (o instanceof Component) {
            removeAllListeners((Component)o,listeners,packages);
        }
        if (o instanceof Window) {
            ((Window)o).dispose();
        }
    }

    public static void annihilateComponent(Object o) {
        annihilateComponent(o,null,null);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM