我的java应用程序中是否有内存泄漏?

时间:2014-03-25 14:13:48

标签: java swing memory-leaks

新增资料:

我在a helpful topic的帮助下尝试了很多东西来摆脱JDialog(参见下面的完整信息)。我在本主题的最后一个答案中重写了代码,添加了一个propertyChangeListener,这似乎是我真正的代码中的问题:
运行,重写代码1:

import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.Timer;

public class RemoveDialogOnruntimeListener extends JFrame {

private static final long serialVersionUID = 1L;
private boolean runProcess;
private int maxLoop = 0;
private Timer timer;
private JOptionPane optionpane;
private JDialog dialog;

public RemoveDialogOnruntimeListener() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setPreferredSize(new Dimension(300, 300));
    setTitle("Remove Dialog On Runtime");
    setLocation(150, 150);
    pack();
    setVisible(true);
    addNewDialog();
}

private void addNewDialog() {
    this.optionpane = new JOptionPane();
    this.dialog = optionpane.createDialog("Foo");
    dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    dialog.setModalityType(Dialog.ModalityType.MODELESS);
    dialog.setVisible(true);
    this.optionpane.addPropertyChangeListener(new PropertyChangeListener() {

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
//              Object obj = evt.getNewValue();
//              System.out.println("----");
//              System.out.println(obj);
            RemoveDialogOnruntimeListener.this.optionpane = null;
            RemoveDialogOnruntimeListener.this.dialog = null;
            remWins();      
            }

        });
    }




private void remWins() {
    runProcess = true;
    timer = new Timer(1000, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (runProcess) {
                for (Window win: Window.getWindows()) {
                    if (win instanceof JDialog) {
                        System.out.println("    Trying to Remove JDialog");
                        win.dispose();
                    }
                }
                System.out.println("    Remove Cycle Done :-)");
                runProcess = false;
                new Thread() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Runtime.getRuntime().gc();
                    }
                }.start();
            } else {
                if(maxLoop>=2){
                    timer.stop();
                } else {
                    pastRemWins();
                    runProcess = true;
                }

            }
        }
    });
    timer.setRepeats(true);
    timer.start();
}

private void pastRemWins() {
    maxLoop++;
    System.out.println("    Checking if still exists any of TopLayoutContainers");
    Window[] wins = Window.getWindows();
    for (int i = 0; i < wins.length; i++) {
        if (wins[i] instanceof JFrame) {
            System.out.println("JFrame");
        } else if (wins[i] instanceof JDialog) {
            System.out.println("JDialog");
        } else {
            System.out.println(wins[i].getClass().getSimpleName());
        }
    }
    // We must expect 2 windows here: this (RemoveDialogOnRuntime) and the parent of all parentless dialogs
    if (wins.length > 2) {
        wins = null;

        if (maxLoop <= 3) {
            System.out.println("    Will Try Remove Dialog again, CycleNo. " + maxLoop);
            System.out.println(" -----------------------------------------------------------");
            remWins();
        } else {
            System.out.println(" -----------------------------------------------------------");
            System.out.println("*** End of Cycle Without Success, Exit App ***");
            closeMe();
        }
    } else {
        timer.stop();
    }
}

private void closeMe() {
    System.exit(0);
}


public static void main(String args[]) {
    RemoveDialogOnruntimeListener superConstructor = new RemoveDialogOnruntimeListener();

}
}

在此示例中,通过使用侦听器,仍将删除JDialog。我尝试将相关代码用于我的实际课程,如下所示:

public class DeleteInsideBox3DDialog {

    Visu3DDeleteInsideBox visu;
    JFormattedTextField xCoord,yCoord,zCoord;
    SimpleTree simpleTree;
    List<Point3D> lastDeleted;
    Object[] options;
    JDialog dialog;
    JOptionPane optionPane;
     private boolean runProcess;
        private int maxLoop = 0;
        private Timer timer;

    public DeleteInsideBox3DDialog(SimpleTree simpleTree, Visu3DDeleteInsideBox visu) {
        this.simpleTree = simpleTree;
        this.visu = visu;
        this.lastDeleted = new ArrayList<Point3D>();
        this.options = new String[] { "Done" };
        Object complexMsg[] = { centerXPanel(),centerYPanel(),centerZPanel()
                ,dimXPanel(),dimYPanel(),dimZPanel()
                ,deleteButtonPanel(),undeleteButtonPanel() };
        this.optionPane = new JOptionPane();

        this.optionPane.setMessage(complexMsg);
        this.optionPane.setOptions(this.options);
        this.optionPane.setMessageType(JOptionPane.PLAIN_MESSAGE);
//          this.dialog = this.optionPane.createDialog(this.simpleTree.getGui()
//                  .getMonitor().getSelectedComponent(),
//                  "Delete Points contained in a box");
            this.dialog = this.optionPane.createDialog("Delete Points contained in a box");
            this.dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        this.dialog.setModalityType(Dialog.ModalityType.MODELESS);
//      this.dialog.setSize(800, 400);
        this.dialog.setVisible(true);
        this.dialog.setVisible(false);
        this.dialog.setVisible(true);
        this.dialog.pack();
        this.optionPane.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                Object obj = evt.getNewValue();
                int result = -1;
                for (int k = 0; k < DeleteInsideBox3DDialog.this.options.length; k++) {
                    if (DeleteInsideBox3DDialog.this.options[k].equals(obj)) {
                        result = k;
                    }
                }

                if (result == 0) {
                    DeleteInsideBox3DDialog.this.optionPane = null;
                    DeleteInsideBox3DDialog.this.dialog.setVisible(false);
                    DeleteInsideBox3DDialog.this.dialog.dispose();
                    DeleteInsideBox3DDialog.this.dialog = null;
                    remWins();  
//                  Visu3DDeleteInsideBox visuOld = (Visu3DDeleteInsideBox) DeleteInsideBox3DDialog.this.simpleTree.getGui().getMonitor().getSelectedComponent();
//                  visuOld.setDialog(null);
//                  DeleteInsideBox3DDialog.this.visu = null;
//                  Monitor monitor = DeleteInsideBox3DDialog.this.simpleTree.getGui().getMonitor();
//                  monitor.removeAll();
//                  monitor.revalidate();
//                  new Thread() {
//                        @Override
//                        public void run() {
//                            try {
//                                Thread.sleep(100);
//                            } catch (InterruptedException e) {
//                                e.printStackTrace();
//                            }
//                            Runtime.getRuntime().gc();
//                        }
//                    }.start();
                    //Visu3dBasic visu = new Visu3dBasic(DeleteInsideBox3DDialog.this.simpleTree, monitor.getWidth(), monitor.getHeight());
                    //monitor.add(visu,DeleteInsideBox3DDialog.this.simpleTree.getModel().getTreeID());
                    //DeleteInsideBox3DDialog.this.optionPane.removeAll();
//                  DeleteInsideBox3DDialog.this.optionPane = null;
                    //DeleteInsideBox3DDialog.this.dialog.setVisible(false);
                    //DeleteInsideBox3DDialog.this.dialog.dispose();
//                  DeleteInsideBox3DDialog.this.dialog = null;
//                  DeleteInsideBox3DDialog.this.remWins();                 
                }

            }
        });
//      this.optionPane = null;
//      this.dialog.setVisible(false);
//      this.dialog.dispose();
//      this.dialog = null;
//      remWins();      

    }

    private void remWins() {
        runProcess = true;
        timer = new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (runProcess) {
                    for (Window win: Window.getWindows()) {
                        if (win instanceof JDialog) {
                            System.out.println("    Trying to Remove JDialog");
                            try {
                                win.getParent().remove(win);
                            } catch (Exception e1) {

                            }
                            ((JDialog) win).setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
                            ((Dialog) win).setModalityType(Dialog.ModalityType.MODELESS);

                            win.dispose();
                        }
                    }
                    System.out.println("    Remove Cycle Done :-)");
                    runProcess = false;
                    new Thread() {
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            Runtime.getRuntime().gc();
                        }
                    }.start();
                } else {
                    if(maxLoop>=2){
                        timer.stop();
                    } else {
                        pastRemWins();
                        runProcess = true;
                    }

                }
            }
        });
        //timer.setRepeats(true);
        timer.start();
    }

    private void pastRemWins() {
        System.out.println("    Checking if still exists any of TopLayoutContainers");
        Window[] wins = Window.getWindows();
        for (int i = 0; i < wins.length; i++) {
            if (wins[i] instanceof JFrame) {
                System.out.println("JFrame");
            } else if (wins[i] instanceof JDialog) {
                System.out.println("JDialog");
            } else {
                System.out.println(wins[i].getClass().getSimpleName());
            }
        }
        // We must expect 2 windows here: this (RemoveDialogOnRuntime) and the parent of all parentless dialogs
        if (wins.length > 2) {
            wins = null;
            maxLoop++;
            if (maxLoop <= 3) {
                System.out.println("    Will Try Remove Dialog again, CycleNo. " + maxLoop);
                System.out.println(" -----------------------------------------------------------");
                remWins();
            } else {
                System.out.println(" -----------------------------------------------------------");
                System.out.println("*** End of Cycle Without Success, Exit App ***");
                //System.exit(0);
                timer.stop();
            }
        } else {
            timer.stop();
        }
    }


}

这没有运行,实际上正在运行的类(删除了JDialog)是同一个类,监听器中包含的5个相关行放在最后,同时删除了监听器。

    public DeleteInsideBox3DDialog(SimpleTree simpleTree, Visu3DDeleteInsideBox visu) {
        this.simpleTree = simpleTree;
        this.visu = visu;
        this.lastDeleted = new ArrayList<Point3D>();
        this.options = new String[] { "Done" };
        Object complexMsg[] = { centerXPanel(),centerYPanel(),centerZPanel()
                ,dimXPanel(),dimYPanel(),dimZPanel()
                ,deleteButtonPanel(),undeleteButtonPanel() };
        this.optionPane = new JOptionPane();

        this.optionPane.setMessage(complexMsg);
        this.optionPane.setOptions(this.options);
        this.optionPane.setMessageType(JOptionPane.PLAIN_MESSAGE);
//          this.dialog = this.optionPane.createDialog(this.simpleTree.getGui()
//                  .getMonitor().getSelectedComponent(),
//                  "Delete Points contained in a box");
            this.dialog = this.optionPane.createDialog("Delete Points contained in a box");
            this.dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        this.dialog.setModalityType(Dialog.ModalityType.MODELESS);
//      this.dialog.setSize(800, 400);
        this.dialog.setVisible(true);
        this.dialog.setVisible(false);
        this.dialog.setVisible(true);
        this.dialog.pack();
//      this.optionPane.addPropertyChangeListener(new PropertyChangeListener() {
//          
//          @Override
//          public void propertyChange(PropertyChangeEvent evt) {
//              Object obj = evt.getNewValue();
//              int result = -1;
//              for (int k = 0; k < DeleteInsideBox3DDialog.this.options.length; k++) {
//                  if (DeleteInsideBox3DDialog.this.options[k].equals(obj)) {
//                      result = k;
//                  }
//              }
//
//              if (result == 0) {
////                    DeleteInsideBox3DDialog.this.optionPane = null;
////                    DeleteInsideBox3DDialog.this.dialog.setVisible(false);
////                    DeleteInsideBox3DDialog.this.dialog.dispose();
////                    DeleteInsideBox3DDialog.this.dialog = null;
////                    remWins();  
////                    Visu3DDeleteInsideBox visuOld = (Visu3DDeleteInsideBox) DeleteInsideBox3DDialog.this.simpleTree.getGui().getMonitor().getSelectedComponent();
////                    visuOld.setDialog(null);
////                    DeleteInsideBox3DDialog.this.visu = null;
////                    Monitor monitor = DeleteInsideBox3DDialog.this.simpleTree.getGui().getMonitor();
////                    monitor.removeAll();
////                    monitor.revalidate();
////                    new Thread() {
////                        @Override
////                        public void run() {
////                            try {
////                                Thread.sleep(100);
////                            } catch (InterruptedException e) {
////                                e.printStackTrace();
////                            }
////                            Runtime.getRuntime().gc();
////                        }
////                    }.start();
//                  //Visu3dBasic visu = new Visu3dBasic(DeleteInsideBox3DDialog.this.simpleTree, monitor.getWidth(), monitor.getHeight());
//                  //monitor.add(visu,DeleteInsideBox3DDialog.this.simpleTree.getModel().getTreeID());
//                  //DeleteInsideBox3DDialog.this.optionPane.removeAll();
////                    DeleteInsideBox3DDialog.this.optionPane = null;
//                  //DeleteInsideBox3DDialog.this.dialog.setVisible(false);
//                  //DeleteInsideBox3DDialog.this.dialog.dispose();
////                    DeleteInsideBox3DDialog.this.dialog = null;
////                    DeleteInsideBox3DDialog.this.remWins();                 
//              }
//              
//          }
//      });
        this.optionPane = null;
        this.dialog.setVisible(false);
        this.dialog.dispose();
        this.dialog = null;
        remWins();      

    }

两个真实代码片段的唯一区别似乎是监听器的使用改变了从工作到不工作的所有内容,但是当我尝试生成示例代码时,监听器的代码也正常工作。

编辑前:

我有一个用于处理地面激光扫描数据的应用程序(介于1 mio和20 mio 3d点之间)。我现在正在清理我的代码并重新编写不同的类。现在我得到了内存使用问题,我不知道它们来自哪里。

基本信息:

OS:Win 7 Ultimate 64 Bit SP1

Ram:16GB

项目执行环境:JavaSE-1.7

由于项目很安静,我想提供一个运行的例子将非常困难。 基本上我用以下参数启动应用程序后的步骤是:

-XX:-UseGCOverheadLimit

-Xms14g

-Xmx14g

以asci格式加载点云,并将它们存储在Point类(类名称Point3D)中,从vecmath lib实现Point3f(抱歉令人困惑的名称)并将其可视化。 执行以下操作之一,这些操作都在我的Gui中调用JDialog:

  • 空间聚类 或

  • 删除删除框内的点

每当我重做其中一个操作时,任务管理器中显示的内存使用量就会增大。让我们坚持删除点。 我按下我的gui按钮,调用以下课程:

1 个答案:

答案 0 :(得分:1)

Java不使用显式内存管理。您对垃圾收集器的调用仅供参考,JVM可能会忽略该调用。此外,免费堆内存通常不会返回给操作系统(例如,它不像C ++删除调用);相反,它假定内存将在Java虚拟机中再次使用,它将管理它。除非我希望JVM 使用,否则我不会给JVM 14GB的堆(-Xms14g -Xmx14g)。