2011-10-28 50 views
5

Ứng dụng Swing (GUI), đích đến của thiết bị đầu cuối thông tin đích. Các VirtualVM profiler cho thấy rò rỉ xảy ra doRò rỉ bộ nhớ trong Swing

java.awt.image.DataBufferInt 

и

sun.awt.image.ImageRepresentation.setPixels 

, sự gia tăng bộ nhớ xảy ra trong quá trình chuyển đổi giữa các loại hình.

Logic ứng dụng là có một số biểu mẫu (JFrame - JF1, JF2 ... JF7). JF1 cơ bản hình thức, nhấn JButtons mở các hình thức khác, và đóng cửa chính nó, vv Ngoại trừ JF1 tất cả các hình thức khác có các nút <>. Trong các hình thức có nhiều JButtons với những hình ảnh, sử dụng 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); 
    } 
} 

Các JButtons trên các hình thức được rút ra như sau:

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

Các lớp học chính mà bắt đầu đầu tiên:

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

Vẫn trong phương thức Init của Biểu mẫu có bộ hẹn giờ, sau một thời gian, mở biểu mẫu chính và đóng biểu mẫu hiện tại:

... 
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 Vui lòng giúp sửa lỗi rò rỉ bộ nhớ.

tôi đã thay đổi tất cả Panel để JPanel và đó là quy tắc ứng 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(); 
    } 
} 

Và thats mới dump

+1

Ông có thể vui lòng giải thích làm thế nào bạn đi đến kết luận rằng đó là một sự rò rỉ? Có phải chỉ vì bộ nhớ phát triển? Bởi vì điều đó có nghĩa là người thu gom rác vẫn chưa chạy. Trừ khi bạn đưa ra các số liệu có ý nghĩa hơn (và không, tôi không tải xuống một tệp rar khỏi rapidshare), thực sự không có cách nào để trợ giúp. –

+0

Vì lỗi OutOfMemoryError. Và tôi theo dõi nó bằng VirtualVM – Daler

Trả lời

4

Bạn có một rò rỉ, nhưng chỉ cần nhìn vào số lượng các lớp được nạp sẽ không giúp bạn tìm ra nó là gì.

Nếu bạn tải ảnh chụp của bạn trong JProfiler (từ chối trách nhiệm: Công ty tôi phát triển JProfiler) và nhìn vào lớn nhất đối tượng xem, bạn có thể thấy rằng bộ nhớ sử dụng là do đôi đệm của nhiều JF1 khung và các trường hợp bảng điều khiển mà thuộc về những khung hình đó.

enter image description here

Vấn đề của bạn là JF1 khung được ẩn nhưng không phải vứt bỏ. Một tìm kiếm cho rễ GC cho thấy rằng tất cả 3 khung hình vô hình được chứa trong java.awt.Window.allWindows mà không thể trường hợp nếu dispose() được gọi. Bạn gọi rất nhiều mã bên ngoài chuỗi gửi sự kiện. Ví dụ, bạn không nên gọi setVisible() từ bộ đếm thời gian. Hãy thử in ra việc tạo ra các khung hình JF1 và các cuộc gọi đến phương pháp vứt bỏ của họ và kiểm tra nơi mà họ không phù hợp.

enter image description here

+0

Đó là nơi tôi vứt bỏ JF1 nếu (GlobalVars.jf3 == null) GlobalVars.jf3 = new JF3(); GlobalVars.jf3.init(); GlobalVars.jf3.setVisible (true); // Так открывается новая форма setVisible (false); // и закрывается текущая vứt bỏ(); – Daler

+0

Sau đó, những dòng này không được gọi. Cố gắng in ra việc tạo ra các JF1 và xử lý của chúng và kiểm tra xem chúng có khớp không. –

+0

Tôi đã thêm mã JF1 và bãi chứa mới – Daler

3

bạn tạo nhiều Top-level Containers, với JComponents hoặc Images bên trong chúng, và những Objects trong biểu mẫu này không bao giờ mất cho JVM Used_Memory, bạn phải làm sạch nội dung chưa sử dụng Top-level Containers,

tốt hơn sẽ là

tạo JFrame chỉ một lần, và cho cửa sổ bật lên một cửa sổ tạo chỉ có một JDialog/JWindow đặt ở đây JPanel, tái sử dụng container này bằng cách loại bỏ JComponents từ JPanel,

JPanel.removeAll(); 

DefaultCloseOperation sẽ

JDialog#setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE)

hoặc bạn có thể đặt

JDialog#setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE) và sau đó bạn có thể gọi chỉ

JDialog#setVisible(false/true) 

EDIT

và bạn phải đóng tất cả các JDBC ResultSet, Statement, PreparedStatement trong khối finally, bởi vì những đối tượng không bao giờ đi từ JVM UsedMemory quá