2010-01-20 40 views
9

Khi sử dụng lớp bên trong ẩn danh làm PropertyChangeListener tại điểm nào trong vòng đời của đối tượng là lớp rác thu thập được? Sau khi lớp chứa (SettingsNode) được khai hoang? Tôi có nên loại bỏ một cách rõ ràng PropertyChangeListener trong finalizer của lớp có chứa (SettingsNode)?Java - Vòng đời lớp bên trong vô danh

public class SettingsNode extends AbstractNode 
{ 
    public SettingsNode(Project project, ProjectSettings projectSettings) 
     throws IntrospectionException 
    { 
     // use an anonymous inner class to listen for changes 
     projectSettings.addPropertyChangeListener(ProjectSettings.PROP_NAME, 
      new PropertyChangeListener() 
      { 
       @Override 
       public void propertyChange(PropertyChangeEvent evt) 
       { 
        // handle event 
       } 
      }); 
    } 
} 
+0

Dựa trên các câu trả lời được cung cấp, một ẩn danh dường như không phải là tùy chọn tốt nhất cho trường hợp sử dụng này. Tôi đang nghĩ một lớp bên trong thể hiện có thể là một lựa chọn tốt hơn, vì tôi có thể giữ một tham chiếu và gọi phương thức removePropertyListener tại một số điểm tương lai. – javacavaj

Trả lời

7

Giống như tất cả các đối tượng, lớp bên trong ẩn danh đủ điều kiện thu gom rác khi tham chiếu cuối cùng không còn tham chiếu đến nó nữa. Tôi đang sử dụng từ ngữ chồn ở đây bởi vì Java không đảm bảo rằng mọi thứ sẽ được GC23 đảm bảo duy nhất là nó sẽ không xảy ra miễn là có một tham chiếu.

Trong trường hợp cụ thể này, đó sẽ là khi projectSettings hoặc thực hiện removePropertyListener() hoặc chính nó là rác được thu thập.

projectSettings tham chiếu lớp bên trong ẩn danh và vì lớp bên trong tham chiếu lớp chứa của nó, điều đó có nghĩa là lớp chứa cũng sẽ tồn tại ít nhất là lớp bên trong.

+0

Mặc dù Java không đảm bảo * khi * một cái gì đó sẽ được GC'd, tôi nghĩ rằng bạn phải nói rằng nó đảm bảo rằng một cái gì đó * sẽ * được GC nếu thay thế là một OutOfMemoryError. – Yishai

+0

Bây giờ bạn đã nói điều đó tôi không còn phải làm gì nữa :) Bạn hoàn toàn đúng, và cảm ơn bạn; nhưng tôi hy vọng không có độc giả nào viết mã phụ thuộc vào hành vi này. –

2

Bạn đang thêm lớp PropertyChangeListener mà bạn đang tạo vào đối tượng projectSettings. PropertyChangeListener đó sẽ không được thu thập miễn là projectSettings tham chiếu đến nó.

2

Trong ví dụ bạn đã hiển thị cả nút cài đặt và trình nghe không thể được xác nhận lại cho đến khi cài đặt dự án được xác nhận lại.

Bạn cần loại bỏ người nghe một cách rõ ràng nhưng có lẽ bạn nên tìm một nơi nào đó đáng tin cậy hơn một người hoàn thiện.

Cài đặtMã sẽ không được khôi phục cho đến sau khi PropertyChangeListener bị xóa. Sử dụng các lớp ẩn danh cho người nghe làm như vậy, đây là nguyên nhân phổ biến gây ra rò rỉ bộ nhớ.

EDIT follwing câu hỏi từ Alex B:

Nếu projectSettings tồn tại cho cuộc sống của các ứng dụng mà bạn không thể loại bỏ người nghe vô danh như bạn không có một tham chiếu đến nó sau khi nó được đăng ký. Vì nhiều cá thể SettingsNode được tạo nên chúng sẽ thêm người nghe của họ vào hàm tạo nhưng chúng sẽ không bao giờ bị loại bỏ vì không ai khác có tham chiếu đến chúng. Điều này sau đó sẽ ngừng các cài đặt SettingsNodes bị xóa cũng như người nghe có tham chiếu đến các cài đặtNode

+0

@Aaron: Bạn có thể đưa ra ví dụ về nơi có rò rỉ bộ nhớ không? –

+0

@Alex: Mã trong câu hỏi thực sự đã là một ví dụ cho rò rỉ bộ nhớ nếu nó không loại bỏ trình nghe khi 'SettingsNode' không còn cần thiết nữa. Xem câu trả lời của Carl giải thích điều này xảy ra. – x4u

0

Một trường hợp điển hình cho rò rỉ bộ nhớ. Sẽ không khuyên bạn nên hoàn thành, vì nó có thể trì hoãn GC.You có thể phơi bày một chức năng làm sạch hoặc ghi đè lên vứt bỏ và bỏ đăng ký.

Thật ngạc nhiên vì sao xích đu không có sẵn trong đăng ký người nghe yếu. Có lẽ bạn có thể thử một số nguồn mở trong giả mạo nguồn?

1

Câu hỏi này khá rõ ràng.

Tuy nhiên, tôi không đồng ý với hầu hết các câu trả lời tại đây.

KHÔNG cần phải loại bỏ người nghe một cách rõ ràng. Trong trường hợp này, đối tượng PropertyChangeListener lớp bên trong sẽ sống cho đến khi cá thể chứa các thiết lập được thu thập.

Bạn thực sự không thể xóa đối tượng PropertyChangeListener vì không có tham chiếu nào được giữ cho nó.

Mặc dù đối tượng PropertyChangeListener tham chiếu đối tượng chứa đối tượng SettingsNode của nó, điều đó không ngăn không cho đối tượng chứa không bị tham chiếu và thu thập rác.

Khi đối tượng chứa đang được bỏ tham chiếu, tất cả các đối tượng chứa bởi SettingsNode sẽ trở thành "đảo cách ly". Tất cả chúng sẽ được thu gom rác.

Các vấn đề liên quan