0

New Information added:

I tried out a lot of stuff to get rid of a JDialog (see full information below) with the help of a helpful topic. I reworked code from last answer in this topic to add a propertyChangeListener, which seems to be in my real code the problem:
running, reworked code 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();

}
}

In this example, with usage of the listener, still the JDialog will be deleted. I tried to work in relevant code to my actual class as follows:

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


}

This is not running, what is actual a running class (where the JDialog is deleted) is the same class with the 5 relevant lines contained in the Listener put to the end with also removing the listener.

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

    }

The only difference in the two real code fragments seems to be the usage of the Listener changing everything from working to not working, but when I tried to produce example code, also the code with the Listener is working.

Before edit:

I have an application written for processing terrestrial laser-scanning data (between 1 mio and 20 mio 3d points). I cleaning up my code right now and reworking different classes. Now I get memory usage issues which I dont know where they come from.

Basic Information:

OS : Win 7 Ultimate 64 Bit SP1

Ram : 16GB

Project execution environment : JavaSE-1.7

As the project is quiet complex, I guess it will be very hard to provide a running example. Basically the steps, after I started my application with following parameters are:

-XX:-UseGCOverheadLimit

-Xms14g

-Xmx14g

Load a point cloud in asci format and store them in a Point class (class name Point3D) implementing Point3f (sorry for confusing names) from vecmath lib and visualize it. Perform one of the following operations, which are all invoking a JDialog in my Gui:

  • spatial clustering or

  • deleting points inside a deletion box

Whenever I redo one of the operations, the memory usage shown in the task manager is enlarged. Lets stick to the deletion of points. I press a button in my gui invoking the following class:

Community
  • 1
  • 1
BuddhaWithBigBelly
  • 345
  • 1
  • 6
  • 15
  • Don't you think this question belongs to [codereview](http://codereview.stackexchange.com/) ? – Not a bug Mar 25 '14 at 14:16
  • 1
    did you reuse JDialog ???, otherwise every a new instance increasing used JVM memory, – mKorbel Mar 25 '14 at 14:18
  • Did not know codereview, can I just "tag" the topic like this or do I have to repost it? – BuddhaWithBigBelly Mar 25 '14 at 14:19
  • What you mean with reuse JDialog? When the performance of an old JDialog is done, I invoke JDialog.dispose(); to free up anything that might be still stored there, but then ofc a new instance of the class deleteInsideBox3DDialog is instanicated. – BuddhaWithBigBelly Mar 25 '14 at 14:22
  • 1
    @BuddhaWithBigBelly your answer (you are looking for) is re_use only one instance of JDialog, [dispose() at runtime == setVisible(false)](http://stackoverflow.com/questions/6309407/remove-top-level-container-on-runtime), garbaged is only peers used for paiting JComponents on the screen, second issue (moreover as bonus in wicked game) if there are close(or their equivalent) all possible resurces from FileIO/JDBC/etc – mKorbel Mar 25 '14 at 14:27
  • 1
    @KishanSarsechaGajjar - No it doesn't. This is question asks for help in debugging ... to find a memory leak. Codereview is for WORKING code. – Stephen C Mar 25 '14 at 14:42
  • @StephenC Ok..I was confused. – Not a bug Mar 25 '14 at 14:43
  • @mKorbel Seems I kind of missunderstood the Api then, public void dispose() Releases all of the native screen resources used by this Window, its subcomponents, and all of its owned children. That is, the resources for these Components will be destroyed, any memory they consume will be returned to the OS, and they will be marked as undisplayable. But if I wanna reuse a Jdiloag again, which I dont have any link anymore in my program, how do I detect the already existing one again? I can either store a link to the Dialog in a parent part in the gui, or maybe perform this with "searching" for – BuddhaWithBigBelly Mar 25 '14 at 14:46
  • @mKorbel an existing JDialog in the JVM. I would have no clue how to do this, so I would try out my first proposed approach. – BuddhaWithBigBelly Mar 25 '14 at 14:48
  • @BuddhaWithBigBelly not, not, not, nothing will be happends, did you tried code in linked question, you are able to display all Top-Level Containers, most of then in the alst known form, `will be marked as undisplayable` - only in the case that exception from RepaintManager to block isDisplayable(), btw then whole instance is addept for kill_me_from_taks_manager – mKorbel Mar 25 '14 at 14:55
  • @mKorbel So first of all, yes you are absolutely right, all of the JDialogs invoked by my program are only "invisible". (Used code from your link to make them visible again). I tried to work through all of your links code, but still not able to "kill" the JDialog, which I guess is the final conclusion from this thread. I also tried to reuse the dialog (added it to the parent gui class and as soon this is instanicated (could also try out final) I never recreate it again. But this is not really working, i created the jdialogs from a Joptionspane, and dont know how to reuse these. – BuddhaWithBigBelly Mar 25 '14 at 17:09
  • @BuddhaWithBigBelly wrote i created the jdialogs from a Joptionspane, and dont know how to reuse these. - use JDialog add WindowListener, then you can listening for, simulating JOPtionPanes statuses CANCELED/CLOSED, can't see there lots of works, but be sute that simple JDialogs/JOPtionPanes don't consume all available JVM memory, there must be some FileIO/JDBC/Socket that isn't close(), those OBjects aren't GC'ed, stays and increasing ..., test with JProfiler, there is tab allocated memory (or something) to check and close all mess, immediatelly and in finally (try-catch-finally) only – mKorbel Mar 25 '14 at 21:01

1 Answers1

1

Java does not use explicit memory management. Your call to the Garbage Collector is advisory only, and the JVM may ignore that call. Further, free heap memory is not generally returned to the operating system (e.g. it's not like a C++ delete call); instead, it assumes that the memory will be used again within the Java Virtual Machine and it will manage that. I would not give the JVM 14GB of heap (-Xms14g -Xmx14g) unless I wanted the JVM to use it.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • @ Elliot frish I guess with the -Xms option I agree kind of with you, but I tried something in the sub Gigabyte and this lead to a out of memory exeption, so for simplicity I just put it to the same value like the maximum heap space. And this, yes I want to give my application the maximum amount of memory, so here 14 GB are fine for me (Used this amount with 20mio data point operations before, though as I said, I am trying to clean up right now). – BuddhaWithBigBelly Mar 25 '14 at 14:36
  • To the first part of your answer, I am aware, that you can never force the GC to work, just give him a nice "please do this for me". I also assumed that the memory is not given back to the OS, but for the JVM it should be now "free memory", so no more memory should be reserved in following process chains. – BuddhaWithBigBelly Mar 25 '14 at 14:40
  • @BuddhaWithBigBelly Only for heap; it might still grow the stack. – Elliott Frisch Mar 25 '14 at 14:42