2011-10-28 20 views
5

Swing de aplicación (GUI), un destino, un terminal de información de destino. El VirtualVM perfilador muestra que la fuga se produce debido aFuga de memoria en Swing

java.awt.image.DataBufferInt 

и

sun.awt.image.ImageRepresentation.setPixels 

, el aumento de la memoria se produce durante las transiciones entre las formas.

La lógica de la aplicación es que hay varias formas (JFrame - JF1, JF2 ... JF7). JF1 forma básica, presionando JButtons abre otras formas, y se cierra, etc. Excepto JF1 todas las otras formas tienen botones <>. En las formas hay muchos JButtons con las imágenes, utilizados FancyButton:

public class FancyButton extends JButton { 
    private static final long serialVersionUID = 1L; 

    public FancyButton(Icon icon, Icon pressed) { 
     super(icon); 
     setFocusPainted(false); 
     //setRolloverEnabled(treue); 
     //setRolloverIcon(rollover); 
     setPressedIcon(pressed); 
     setBorderPainted(false); 
     setContentAreaFilled(false); 
    } 
} 

Los JButtons en los formularios se dibujan como sigue:

public class JF1 extends JFrame { 

    private static final GridBagConstraints gbc; 
    public static Timer tmr; 

    public JF1() throws Exception{ 
     setUndecorated(true); 
     GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this); 
     setAlwaysOnTop(true); 
     setLayout(new GridBagLayout()); 
     setTitle("JF1"); 
    } 

    public void init() throws Exception{ 

     GlobalVars.jf2 = null; 
     GlobalVars.jf3 = null; 
     GlobalVars.jf4 = null; 
     GlobalVars.jf5 = null; 
     GlobalVars.jf6 = null; 
     GlobalVars.jf7 = null; 
     JXPanel contentPane = new JXPanel(); 
       try { 
       ImagePainter ip = new ImagePainter(ImageIO.read(new File("skins/bg.jpg"))); 
       ip.setFillHorizontal(true); 
       ip.setFillVertical(true); 
       contentPane.setBackgroundPainter(ip); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 


     Panel p01 = new Panel(); 
     GridLayout gl01 = new GridLayout(1, 8, 2, 2); 
     p01.setLayout(gl01); 
     p01.setLocation(200, 300); 
     ResultSet rs = GlobalVars.st.executeQuery("select * from last_use_service order by nomer"); 
     Icon i1; 
     Icon i2; 
     while (rs.next()){ 
      final int l = rs.getInt(2); 
      i1 = new ImageIcon("skins/oper_logos/" + l + ".png"); 
      i2 = new ImageIcon("skins/oper_logos/" + l + "_off.png"); 

      FancyButton jbt = new FancyButton(i1,i2); 
      jbt.setBounds(10, 100, 100, 100); 

      jbt.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        tmr.stop();  

        if(GlobalVars.jf3==null) 
              GlobalVars.jf3 = new JF3(); 
        GlobalVars.jf3.init(); 
        GlobalVars.jf3.setVisible(true);   // Так открывается новая форма 
        setVisible(false);        // и закрывается текущая 
        dispose(); 
       } 
      }); 
      p01.add(jbt); 
     } 
     rs.close(); 
     addComponent(panel, p01, 0, 1, 2, 1, GridBagConstraints.WEST,GridBagConstraints.NORTHWEST); 
... 

La clase principal que comienza primero:

public class Main { 

    public static class GlobalVars{ 

     public static String TypeDB = "MySQL"; 
     public static Connection DataBase; 
     public static Statement st;  

     public static JF1 jf1;   // JFrame 
     public static JF2 jf2;   // JFrame 
     public static JF3 jf3;   // JFrame 
     ... 
    } 

    public static void main(String[] args) throws Exception { 
     if(GlobalVars.TypeDB.equals("MySQL")){ 
      Class.forName("com.mysql.jdbc.Driver"); 
      GlobalVars.DataBase = DriverManager.getConnection("jdbc:mysql://localhost:3306/terminal?lc_ctype=UTF8", "root","123"); 

       if(GlobalVars.jf1==null) 
        GlobalVars.jf1 = new JF1(); 
     GlobalVars.jf1.init(); 
     GlobalVars.jf1.setVisible(true); 
     } 
... 
     } 

Todavía en el método Init de Forms tiene un temporizador que, después de un tiempo, abre el formulario principal y cierra el actual:

... 
tmr = new Timer(s * 1000, updateCursorAction); 
tmr.start(); 
... 
private Action updateCursorAction = new AbstractAction() { 
     public void actionPerformed(ActionEvent e) { 
      if(GlobalVars.jf1==null){ 
       try { 
        GlobalVars.jf1= new JF1(); 
       } catch (Exception e1) { 
        e1.printStackTrace(); 
       } 
      } 
      tmr.stop(); 
      try { 
       GlobalVars.jf1.init(); 
      } catch (Exception e1) { 
       e1.printStackTrace(); 
      } 
      GlobalVars.jf1.setVisible(true); 
      GlobalVars.jf2 = null; 
      setVisible(false); 
      dispose();  
     } 
    }; 

HEAP DUMP Por favor, ayuda a solucionar una fuga de memoria.

me había cambiado todo Panel de JPanel y que es el código de JF1:

package PlatService; 

import java.awt.*; 

public class JF1 extends JFrame { 
    private static final long serialVersionUID = 1L; 
    //private static final Insets insets = new Insets(0, 0, 0, 0); 
    private static String[] arrLang = { "rus", "eng", "taj" }; 
    private static final GridBagConstraints gbc; 
    public static Timer tmr; 

    static { 

    public JF1() throws Exception{ 
     setUndecorated(true); 
     GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this); 
     setAlwaysOnTop(true); 
     setLayout(new GridBagLayout()); 
     setTitle("JF1"); 
    } 

    public void init() throws Exception{ 

     GlobalVars.jf2 = null; 
     GlobalVars.jf3 = null; 
     GlobalVars.jf4 = null; 
     GlobalVars.jf5 = null; 
     GlobalVars.jf6 = null; 
     GlobalVars.jf7 = null; 
     JXPanel contentPane = new JXPanel(); 
     try { 
       ImagePainter ip = new ImagePainter(ImageIO.read(new File("skins/bg.jpg"))); 
       ip.setFillHorizontal(true); 
       ip.setFillVertical(true); 
       contentPane.setBackgroundPainter(ip); 
     } catch (Exception e) { 
       e.printStackTrace(); 
     } 
     //setContentPane(contentPane); 
     JPanel panel = new JPanel(); 
     panel.setLayout(new GridBagLayout()); 
     addComponent(this, panel, 0, 0, 1, 1, GridBagConstraints.CENTER ,GridBagConstraints.BOTH); 

     JPanel p0 = new JPanel(); 
     GridLayout gl0 = new GridLayout(1, 1, 1, 1); 
     final JLabel jl = new JLabel(new ImageIcon("skins/logo.png")); 
     p0.setLayout(gl0); 
     p0.add(jl); 
     addComponent(panel, p0, 0, 0, 2, 1, GridBagConstraints.NORTH ,GridBagConstraints.NORTH); 


     JPanel p01 = new JPanel(); 
     GridLayout gl01 = new GridLayout(1, 8, 2, 2); 
     p01.setLayout(gl01); 
     p01.setLocation(200, 300); 
     ResultSet rs = GlobalVars.st.executeQuery("select * from last_use_service order by nomer"); 
     Icon i1; 
     Icon i2; 
     while (rs.next()){ 
      final int l = rs.getInt(2); 
      i1 = new ImageIcon("skins/oper_logos/" + l + ".png"); 
      i2 = new ImageIcon("skins/oper_logos/" + l + "_off.png"); 
      FancyButton jbt = new FancyButton(i1,i2); 
      jbt.setBounds(10, 100, 100, 100); 
      jbt.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        tmr.stop(); 
        GlobalVars.OperId = l; 
        GlobalVars.getCashCode=false; 
        if(GlobalVars.jf3==null)GlobalVars.jf3 = new JF3(); 
        GlobalVars.jf3.init(); // = new JF3(); 
        GlobalVars.jf3.setVisible(true); 
        setVisible(false); 
        dispose(); 
       } 
      }); 
      p01.add(jbt); 
     } 
     rs.close(); 
     addComponent(panel, p01, 0, 1, 2, 1, GridBagConstraints.WEST,GridBagConstraints.NORTHWEST); 

     if (GlobalVars.LangId < 0 || GlobalVars.LangId > 2)GlobalVars.LangId = 0; 

     String sql = "SELECT * FROM OpGroup WHERE parent=0 order by enable desc, order_n"; 
     PreparedStatement psmnt = GlobalVars.DataBase.prepareStatement(sql); 
     ResultSet rs2 = psmnt.executeQuery(); 

     //rs = GlobalVars.st.executeQuery(); 
     JPanel p = new JPanel(); 
     GridLayout gl = new GridLayout(0, 2, 2, 2); 
     p.setLayout(gl); 
     p.setSize(300, 400); 
     p.setLocation(200, 300);   
     while (rs2.next()){ 
      final int l = rs2.getInt(2); 
      i1 = new ImageIcon("skins/"+ arrLang[GlobalVars.LangId]+"/services/" + l + ".png"); 
      i2 = new ImageIcon("skins/"+ arrLang[GlobalVars.LangId]+"/services/" + l + "_off.png"); 
      FancyButton jbt = new FancyButton(i1,i2); 
      jbt.setBounds(10, 100, 100, 100); 
      if(rs2.getInt("enable")==1){ 
       jbt.setEnabled(true); 
      }else{ 
       jbt.setEnabled(false); 
      } 
      jbt.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        GlobalVars.getCashCode=false; 
        try { 
         tmr.stop(); 
         ActionPerformed(event, GlobalVars.LangId, l); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      }); 
      p.add(jbt); 
     } 
     addComponent(panel, p, 0, 2, 1, 1, GridBagConstraints.NORTH,GridBagConstraints.NORTH); 
     rs2.close(); 
     JPanel p1 = new JPanel(); 
     GridLayout gl1 = new GridLayout(5, 1, 5, 5); 
     // setLayout(new GridLayout(3, 4, 2, 2)); 
     p1.setLayout(gl1); 
     // p2.setSize(300, 400); 
     // p2.setLocation(200, 300); 

     for (int i = 0; i < arrLang.length; i++) { 
      final int l = i; 
      i1 = new ImageIcon("skins/button_" + arrLang[i] + ".png"); 
      i2 = new ImageIcon("skins/button_" + arrLang[i] + "_off.png"); 
      FancyButton jbt = new FancyButton(i1, i2); 
      jbt.setBounds(10, 100, 100, 100); 
      //if (i == GlobalVars.LangId) {jbt.setEnabled(false);} 
      jbt.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        //Play.stop(); 
        GlobalVars.LangId = l; 
        GlobalVars.getCashCode=false; 
        GlobalVars.jf1 = null; 
        try { 
         GlobalVars.jf1 = new JF1(); 
        } catch (Exception e1) { 
         e1.printStackTrace(); 
        } 
        try { 
         GlobalVars.jf1.init(); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
        tmr.stop(); 
        GlobalVars.jf1.setVisible(true); 
        setVisible(false); 
       } 
      }); 
      p1.add(jbt); 
     } 
     i1 = new ImageIcon("skins/" + arrLang[GlobalVars.LangId] + "/services/button_help.png"); 
     i2 = new ImageIcon("skins/" + arrLang[GlobalVars.LangId] + "/services/button_help_off.png"); 
     FancyButton jbt_help = new FancyButton(i1,i2); 
     jbt_help.setBounds(10, 100, 100, 100); 
     jbt_help.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent event) { 
       tmr.stop(); 
       GlobalVars.getCashCode=false; 
       GlobalVars.jf1 = null; 
       try { 
        GlobalVars.jf1 = new JF1(); 
       } catch (Exception e1) { 
        e1.printStackTrace(); 
       } 
       try { 
        GlobalVars.jf1.init(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
       GlobalVars.jf1.setVisible(true); 
       setVisible(false); 
      } 
     }); 
     p1.add(jbt_help); 
     i1 = new ImageIcon("skins/" + arrLang[GlobalVars.LangId] + "/services/button_about.png"); 
     i2 = new ImageIcon("skins/" + arrLang[GlobalVars.LangId] + "/services/button_about_off.png"); 
     FancyButton jbt_about = new FancyButton(i1,i2); 
     jbt_about.setBounds(10, 100, 100, 100); 

     p1.add(jbt_about); 
     addComponent(panel, p1, 1, 2, 1, 1, GridBagConstraints.EAST,GridBagConstraints.EAST); 

     JPanel p011 = new JPanel(); 
     GridLayout gl011 = new GridLayout(1, 1, 1, 1); 
     gl011.setVgap(1); 
     JLabel jl12 = new JLabel("<html><hr></html>", JLabel.LEFT); 
     jl12.setAlignmentX(TOP_ALIGNMENT); 
     jl12.setBackground(Color.red); 
     p011.setLayout(gl011); 
     p011.add(jl12); 
     p011.setSize(10, 90); 
     addComponent(panel, p011, 0, 3, 4, 1, GridBagConstraints.WEST, GridBagConstraints.NORTH); 


     JPanel p0112 = new JPanel(); 
     GridLayout gl0112 = new GridLayout(1, 1, 1, 1); 
     gl0112.setVgap(1); 
     JLabel jl122 = new JLabel("<html><hr><H2>"+GlobalVars.StatusMessage[GlobalVars.LangId]+"</H2></html>", JLabel.CENTER); 
     jl122.setAlignmentX(TOP_ALIGNMENT); 
     p0112.setLayout(gl0112); 
     p0112.add(jl122); 
     p0112.setSize(10, 90); 

     addComponent(this, p0112, 0, 5, 5, 1, GridBagConstraints.SOUTH, GridBagConstraints.BOTH); 

     if(!GlobalVars.stTerminal.equals("301")){ 
      GlobalVars.stTerminal = "301"; 
      String sql1 = "INSERT INTO perif_status (perif,state,date_change) values('terminal','"+GlobalVars.stTerminal+"',UNIX_TIMESTAMP())"; 
      //System.out.println(sql1); 
      try { 
       GlobalVars.st.execute(sql1); 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      } 
     } 
     GlobalVars.NomerAb=""; 
     GlobalVars.GroupId = 0; 
     GlobalVars.getCashCode=true; 
     tmr = new Timer(1000, updateCursorAction); 
     tmr.start(); 

     System.gc(); 
    } 

    public void update(){ 

    private Action updateCursorAction = new AbstractAction() { 
     public void actionPerformed(ActionEvent e) { 
      if(GlobalVars.doBlock){ 
       if(!GlobalVars.stTerminal.equals("303")){ 
        GlobalVars.stTerminal = "303"; 
        String sql1 = "INSERT INTO perif_status (perif,state,date_change) values('terminal','"+GlobalVars.stTerminal+"',UNIX_TIMESTAMP())"; 
        String sql2 = "UPDATE settings set value='"+GlobalVars.stTerminal+"' WHERE variable='terminal_state'"; 
        System.out.println(sql1); 
        System.out.println(sql2); 
        try { 
         GlobalVars.st.execute(sql1); 
        } catch (SQLException e1) { 
         e1.printStackTrace(); 
        } 
        try { 
         GlobalVars.st.execute(sql2); 
        } catch (SQLException e1) { 
         e1.printStackTrace(); 
        } 
       }  
       String sql1 = "UPDATE commands SET status=1, date_execute=UNIX_TIMESTAMP() WHERE id_on_server="+GlobalVars.doCommandId; 
       System.out.println(sql1); 
       try { 
        GlobalVars.st.execute(sql1); 
       } catch (SQLException e1) { 
        e1.printStackTrace(); 
       } 
       if(GlobalVars.jf7==null) 
        try { 
         GlobalVars.jf7= new JF7(); 
        } catch (Exception e1) { 
         e1.printStackTrace(); 
        } 
       try { 
        GlobalVars.jf7.init(); 
       } catch (Exception e1) { 
        e1.printStackTrace(); 
       } 


       GlobalVars.doBlock=false; 
       GlobalVars.doCommandId = 0; 
       GlobalVars.jf7.setVisible(true); 
       GlobalVars.jf1 = null; 
       setVisible(false); 
       tmr.stop(); 
       setVisible(false); 
       dispose(); 
      } 
     } 
    }; 

    private static void addComponent(Container container, Component component,int gridx, int gridy, int gridwidth, int gridheight, int anchor,int fill) { 
     Insets ins = new Insets(0, 0, 0, 0); 
     GridBagConstraints gbc1 = new GridBagConstraints(gridx, gridy,gridwidth, gridheight, 1.0, 1.0, anchor, fill, ins, 0, 0); 
     container.add(component, gbc1); 
    } 

    public void ActionPerformed(ActionEvent event, int lID,int gId) throws Exception { 
     GlobalVars.GroupId = gId; 
     if(GlobalVars.jf2==null)GlobalVars.jf2 = new JF2(); 
     GlobalVars.jf2.init(); 
     GlobalVars.jf2.setVisible(true); 
     setVisible(false); 
     dispose(); 
    } 
} 

Y eso es nuevo dump

+1

Podría explicar cómo se llegó a la conclusión de que se trata de una fuga? ¿Es solo porque la memoria crece? Porque eso puede significar que el recolector de basura no se ha ejecutado todavía. A menos que proporcione métricas más significativas (y no, no estoy descargando un archivo rar de rapidshare), realmente no hay forma de ayudar. –

+0

debido a OutOfMemoryError. Y lo controlo mediante VirtualVM – Daler

Respuesta

4

Usted tiene una fuga, pero solo mirando el número de clases cargadas no le ayudará a descubrir de qué se trata.

Si carga la instantánea en JProfiler (aclaración: mi empresa desarrolla JProfiler) y mirar a la mayor objetos de vista, se puede ver que la memoria utilizada se debe a la doble buffer de múltiples JF1 marcos y las instancias de panel que pertenecen a esos marcos.

enter image description here

Su problema es que los JF1 marcos están ocultos pero no eliminarse. Una búsqueda de raíces de GC muestra que los 3 cuadros invisibles están contenidos en java.awt.Window.allWindows, lo que no ocurre si se llama al dispose(). Llamas a un montón de código fuera del hilo de envío del evento. Por ejemplo, no debe llamar a setVisible() desde el hilo del temporizador. Intente imprimir la creación de fotogramas JF1 y la llamada a sus métodos de eliminación y compruebe dónde no coinciden.

enter image description here

+0

Ahí es donde dispongo de JF1 if (GlobalVars.jf3 == null) GlobalVars.jf3 = nuevo JF3(); GlobalVars.jf3.init(); GlobalVars.jf3.setVisible (true); // Так открывается новая форма setVisible (falso); // и закрывается текущая dispose(); – Daler

+0

Entonces estas líneas no son llamadas. Intente imprimir la creación de JF1 y su eliminación y verifique si coinciden. –

+0

He agregado el código JF1 y el nuevo volcado – Daler

3

a crear un montón de Top-level Containers, con JComponents o Images dentro de ellos, y estos Objects en esta forma nunca se ha ido para JVM Used_Memory, usted tiene que limpiar el contenido de Top-level Containers,

mejor sería

crear JFrame una sola vez, y por otro emergente ventanas crean una sola JDialog/JWindow poner aquí JPanel, reutilizar este Container mediante la eliminación de JComponents de JPanel,

JPanel.removeAll(); 

DefaultCloseOperation sería

JDialog#setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE)

o puede configurar

JDialog#setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE) y luego sólo puede llamar a

JDialog#setVisible(false/true) 

EDITAR

y hay que cerrar todas JDBC ResultSet, Statement, PreparedStatement en bloque finally, ya que estos objetos nunca se ha ido de JVM UsedMemory demasiado