2009-10-01 5 views
1

Java fuite de mémoireJava mémoire Problème de fuite avec JPanels

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

}

Le problème qui se produit est que je reçois de plus en plus de messages mon utilisation de la mémoire de programme Java ne cesse de croître par la suite l'amenant à se bloquer en haut J'ai isolé ma fuite de mémoire au code ci-dessus spécifiquement l'appel de procédure d'ajout. Je suppose que le removeAll effacerait le contenu de mon panneau, mais il semble toujours continuer à croître.

Note: Le message.buildGUI() retourne un JPanel qui est affiché sur le responsePanel

Suivi:

Le code BuildGUI apparaît comme tel

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; 

Il n'y a pas les auditeurs Le panneau renvoyé est uniquement à des fins d'affichage.

+0

Juste curieux de savoir pourquoi vous marquer tous ces composants comme "finale." Voulez-vous vraiment que ces valeurs soient attribuées une seule fois et/ou essayez-vous d'obtenir un gain de performance? De plus, de combien de composants GUI parle-t-on dans la méthode "buildGUI()"? 5 de plus? 100 de plus? 1 million de plus? – JasCav

+0

Est-ce que le responsePanel a une disposition personnalisée par hasard? – user101884

+0

J'utilise l'outil SWTDesign dans Eclipse pour générer automatiquement le code de l'interface graphique, c'est pourquoi tout est marqué comme final. En réalité, le composant GUI ne devrait jamais changer parce que c'est une sorte de sortie seulement. Le ResponsePannel est comme GridBagLayout. Toujours aucune idée de comment résoudre ce problème. –

Répondre

5

La méthode buildGUI permet-elle d'ajouter des écouteurs à vos objets métier? C'est une source commune de fuites de mémoire. L'appel responsePanel.removeAll() va supprimer les composants, mais les composants peuvent toujours être enregistrés en tant qu'auditeurs sur le responsePanel ou d'autres objets, entraînant leur conservation en mémoire.

1

Voici Une solution au problème de fuite de mémoire removeAll() ...
Je l'appelle l'anéantissement des composants.

Ce n'est pas très efficace et je ne recommanderais pas de l'utiliser sauf si vous en avez vraiment besoin.
Il peut être accéléré en spécifiant les types d'écouteurs à rechercher.

Remarque: Il supprime le LayoutManager du panneau, vous devez donc l'ajouter de nouveau.

Exemples d'utilisation:


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

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