2011-10-28 22 views
5

Un'applicazione Swing (GUI), una destinazione un terminale di informazioni di destinazione. La VirtualVM profiler mostra che la perdita si verifica a causa diPerdita di memoria in Swing

java.awt.image.DataBufferInt 

и

sun.awt.image.ImageRepresentation.setPixels 

, l'aumento di memoria si verifica durante le transizioni tra forme.

La logica dell'applicazione è che esistono diversi moduli (JFrame - JF1, JF2 ... JF7). JF1 forma base, premendo i JButton si aprono altri moduli e si chiude, ecc. Tranne JF1 tutte le altre forme hanno i pulsanti <>. Nelle forme ci sono molti JButtons con tabelle, utilizzate 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); 
    } 
} 

Le JButtons sulle forme sono disegnate come segue:

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 classe principale che inizia prima:

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

Ancora nel metodo Init di Forms ha un timer che, dopo un po ', apre il modulo principale e chiude quello attuale:

... 
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 Si prega di contribuire a risolvere una perdita di memoria.

avevo cambiato tutto Pannello di JPanel e che è il codice di 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(); 
    } 
} 

E questo nuovo dump

+1

Potrebbe spiegare come siete arrivati ​​alla conclusione che si tratta di una fuga di notizie? È solo perché cresce la memoria? Perché ciò potrebbe significare solo che il garbage collector non è ancora stato eseguito. A meno che non forniate metriche più significative (e no, non sto scaricando un file rar da rapidshare), non c'è davvero alcun modo di aiutare. –

+0

A causa di OutOfMemoryError. E lo monitoro con VirtualVM – Daler

risposta

4

Hai una perdita, ma solo guardando il numero di classi caricate non ti aiuterà a scoprire di cosa si tratta.

Se si carica l'istantanea in JProfiler (disclaimer: la mia azienda sviluppa JProfiler) e guardare il più grande visualizzare gli oggetti, si può vedere che la memoria utilizzata è dovuto al doppio buffer di multipla JF1 cornici e le istanze del pannello che appartengono a quelle cornici.

enter image description here

Il tuo problema è che le JF1 telai sono nascosti, ma non smaltiti. Una ricerca per le radici GC mostra che tutti e 3 i fotogrammi invisibili sono contenuti in java.awt.Window.allWindows, il che non è possibile se viene chiamato dispose(). Si chiama un sacco di codice al di fuori del thread di invio dell'evento. Ad esempio non si dovrebbe chiamare setVisible() dal thread del timer. Prova a stampare la creazione dei frame JF1 e la chiamata ai loro metodi di smaltimento e controlla dove non corrispondono.

enter image description here

+0

Ecco dove dispongo JF1 se (GlobalVars.jf3 == null) GlobalVars.jf3 = new JF3(); GlobalVars.jf3.init(); GlobalVars.jf3.setVisible (true); // Так открывается новая форма setVisible (false); // и закрывается текущая dispose(); – Daler

+0

Quindi queste righe non vengono chiamate. Prova a stampare la creazione di JF1 e la loro disposizione e controlla se corrispondono. –

+0

Ho aggiunto il codice JF1 e il nuovo dump – Daler

3

si crea un sacco di Top-level Containers, con JComponents o Images al loro interno, e questi Objects in questo modulo non è mai andato per JVM Used_Memory, è necessario ripulire il contenuto non utilizzato Top-level Containers,

meglio sarebbe

creare JFrame una sola volta e per un altro pop-up finestre creano un solo JDialog/JWindow mettere qui JPanel, riutilizzare questo contenitore rimuovendo JComponents da JPanel,

JPanel.removeAll(); 

DefaultCloseOperation sarebbe

JDialog#setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE)

oppure è possibile impostare

JDialog#setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE) e quindi è possibile chiamare solo

JDialog#setVisible(false/true) 

EDIT

e si deve chiudere tutte ResultSet JDBC, Normativa, PreparedStatement nel blocco finally, perché questi oggetti mai andato da JVM UsedMemory troppo