java-private内部类实例没有收集垃圾

时间:2017-03-05 05:20:47

标签: java javafx memory-leaks garbage-collection

我之前已经知道有关非静态内部类的内存泄漏的问题。我阅读了问题thisthis,但我并不完全明白我的错误。

我的课程如下

    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
            }
        }
    }

AddNewProductDialog(外部)类是一个单例类,它有一个辅助类AddNewProductDialogHelper。此助手类设置TextInputDialog newProductName

的属性

我在调用类build的{​​{1}}方法后跟AddNewProductDialog方法调用show 每次点击按钮以获取用户输入

我希望AddNewProductDialog.getInstance().build().show()的实例在初始化AddNewProductDialogHelper newProductName之后进行垃圾回收

问题是,dialog box的实例正在堆内存中出现并且没有收集垃圾。每次我点击按钮获取用户输入时,都会创建一个新实例,并且在点击按钮时它会继续起作用

然而,当我评论此代码块时

AddNewProductDialogHelper

可行,之前的实例 会收集垃圾。 为什么评论此代码块有效?

我正在使用VisualVM来检查堆转储

1 个答案:

答案 0 :(得分:1)

您正在将这些内部对象作为侦听器添加到侦听器列表中。

因此有一个参考保留给他们。

所以我认为问题不在你声称引起麻烦的部分,而是上面的那一行。只要您不以某种方式从该侦听器列表中删除内部对象,就无法对其进行垃圾回收。

所以解决方案可能很复杂:你应该退后一步并改变你的方法......你需要能够记住这些内部对象,以便你可以在某个时候取消注册它们。

除此之外:奇怪的设计。也很难为我测试。