JPanels的Java内存泄漏问题

时间:2009-10-01 14:26:51

标签: java

Java内存泄漏

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

}

正在发生的问题是当我收到越来越多的消息时,我的Java程序的内存使用量继续增长,最终导致其锁定。我已将内存泄漏隔离到上面的代码,特别是添加过程调用。我假设removeAll会清除我面板的内容,但它似乎仍在继续增长。

注意:message.buildGUI()返回一个显示在responsePanel上的JPanel

跟进:

BuildGUI代码如此显示

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;

没有监听器,返回的面板仅用于显示目的。

2 个答案:

答案 0 :(得分:5)

buildGUI方法是否为您的业务对象添加了侦听器?这是内存泄漏的常见原因。调用responsePanel.removeAll()将删除组件,但组件仍可能在responsePanel或其他对象上注册为侦听器,从而导致它们保留在内存中。

答案 1 :(得分:1)

这是解决removeAll()内存泄漏问题的 A 解决方案...
我称之为组件毁灭。

效率不高,除非你真的需要,否则我不建议使用它 可以通过指定要查找的侦听器类型加快速度。

注意:它会从面板中删除LayoutManager,因此您需要重新添加它。

使用示例:


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);
}

以下是代码:


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);
    }
}