【问题标题】:java-private inner class instances not getting garbage collectedjava-private内部类实例没有被垃圾收集
【发布时间】:2017-03-05 05:20:46
【问题描述】:

我知道关于非静态内部类的内存泄漏的问题之前已经被问过。我阅读了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的属性

我调用AddNewProductDialog 类的build 方法,然后调用show 方法作为AddNewProductDialog.getInstance().build().show() 每次单击按钮 以获取用户输入。

我希望 AddNewProductDialogHelper 的实例在完成初始化 newProductName dialog box 后被垃圾回收

问题是,AddNewProductDialogHelper 的实例在堆内存中堆积并且没有被垃圾收集。每次我单击按钮以获取用户输入时,都会创建一个新实例,并且在单击按钮时它会不断堆积

然而,当我评论这个代码块时

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

它可以工作,之前的实例正在被垃圾收集。 为什么注释此代码块有效?

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

【问题讨论】:

  • isInputValid 是您的助手的方法,然后在侦听器的关闭中。

标签: java javafx memory-leaks garbage-collection


【解决方案1】:

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

因此保留了对它们的引用。

所以我认为问题不在于您声称造成麻烦的部分,而在于上面的那一行。只要您不以某种方式从该侦听器列表中删除内部对象,它们就不能被垃圾收集。

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

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

【讨论】:

  • 感谢我们的回复。感谢您帮助确定正确的设计方法。
  • 抱歉,a) 我在我的手机上,b) 这需要就您的要求和您试图解决的问题进行多次交流......这不是这个社区的意义所在。我们帮助解决编程问题,而不是构建整个应用程序。
  • @Nishant123 问题解决后,CR 可能是适合您的站点。
  • @maaartinus 谢谢!!
猜你喜欢
  • 2020-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 2011-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多