简体   繁体   中英

java-private inner class instances not getting garbage collected

I know questions regarding memory leak for non-static inner classes have already been asked before. I read questions this and this but I don't fully understand what wrong am I doing.

My class is as below

    public class AddNewProductDialog {
        private static AddNewProductDialog dialog;
        private TextInputDialog newProductName = new TextInputDialog();

        private AddNewProductDialog(){
        }

        public static AddNewProductDialog getInstance(){
            if(dialog == null){
                dialog = new AddNewProductDialog();
            }
            return dialog;
        }

        /*Helper Class start*/
        private class AddNewProductDialogHelper{

            private void initializeDialog(){ //---> Prepare a dialog box
                newProductName.setTitle("Add New Product");
                newProductName.setHeaderText("Note: This product name will be used as bat script file name. Eg. call_<productname>_script");
                newProductName.setContentText("Product Name :");
                newProductName.getDialogPane().lookupButton(ButtonType.OK).setDisable(true);

/*Something over here*/
                newProductName.getEditor().textProperty().addListener(new ChangeListener<String>() {
                    @Override
                    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                        // TODO Auto-generated method stub
                        if(isInputvalid(newProductName.getEditor().getText())){
                            newProductName.getDialogPane().lookupButton(ButtonType.OK).setDisable(false);
                        }
                    }
                });
            }

            private boolean isInputvalid(String text){
                if(text.trim().length() > 0)
                    return true;
                return false;
            }

        }
        /*Helper class end*/

        public AddNewProductDialog build(){
            new AddNewProductDialogHelper().initializeDialog();
            return this;
        }

        public void show() {
            Optional<String> result = newProductName.showAndWait();
            if(result.isPresent()){
                //----> handle the input
            }
        }
    }

The AddNewProductDialog (outer) class is a singleton class which has a helper class AddNewProductDialogHelper . This helper class sets the properties of TextInputDialog newProductName

I am calling the build method of class AddNewProductDialog followed by show method as AddNewProductDialog.getInstance().build().show() everytime a button is clicked to take user input.

I want the instance of the AddNewProductDialogHelper to be garbage collected after it is done initializing newProductName dialog box

The problem is that, the instances of AddNewProductDialogHelper are pilling up in Heap memory and are not getting garbage collected. Everytime I click the button to get user input a new instance is getting created and it keeps on pilling up as the button is clicked

However , when I comment this code block

newProductName.getEditor().textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    // TODO Auto-generated method stub
                    if(isInputvalid(newProductName.getEditor().getText())){
                        newProductName.getDialogPane().lookupButton(ButtonType.OK).setDisable(false);
                    }
                }
            });

it works and previous instances are getting garbage collected. Why does commenting this code block works?

I am using VisualVM to check my heap dump

You are adding those inner objects as listeners to a listener list.

Thus there is a reference kept to them.

So I think the problem is not in the section that you claim to cause trouble, but the line above. As long as you don't somehow remove the inner objects from that listener list they can't be garbage collected.

So the solution is probably complicated: you should step back and change your approach... You need to be able to remember these inner objects so that you can unregister them at some point.

And beyond that: strange design. Also looks hard to test for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM