2017-03-05 33 views
0

我知道关于非静态内部类的内存泄漏的问题已经被问过。我读过的问题是thisthis,但我不完全明白我在做什么错。java私有的内部类实例没有被垃圾收集

我的类是如下

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的实例是做初始化newProductNamedialog 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检查我堆转储

+0

'isInputValid'是您的帮助器的方法,然后在侦听器的关闭中。 –

回答

1

你加入这些内部对象作为听众的收听列表。

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

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

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

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

+0

感谢我们的回复。希望你能帮助确定正确的设计方法。 – Nishant123

+0

对不起,a)我在我的手机上,b)需要许多关于您的要求和您尝试解决的问题的许多交流......而这不是这个社区的意图。我们帮助解决编程问题,而不是构建整个应用程序。 – GhostCat

+0

@ Nishant123问题解决后,[CR](http://codereview.stackexchange。com/questions/tagged/java)可能是您正确的网站。 – maaartinus