2017-03-05 69 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