2010-08-11 16 views
6

Tôi có một ứng dụng trình duyệt Swing với một lỗi khi tôi thêm/xóa vào/từ GUI bộ nhớ không được phát hành cho các đối tượng đó và tôi đang cố gắng theo dõi những gì đang nắm giữ trên chúng. Vấn đề là tôi không biết làm thế nào để biết khi nào một cái gì đó thực sự được giải phóng hoàn toàn khỏi ký ức.Làm thế nào để biết khi nào bộ nhớ của một đối tượng Java được phát hành?

Có cách nào để biết một đối tượng đã được giải phóng khỏi bộ nhớ không? Tôi đã quen với Objective-C, nơi có nhiều cách để nói.

Cảm ơn

+0

(FWIW, thường là người nghe) –

+0

Tôi nghĩ có thể nhưng tôi đã cố gắng loại bỏ tất cả actionListeners và componentListeners – Shizam

Trả lời

6

Bạn thực sự không thể thực hiện điều đó trong Java. Tất cả các câu trả lời đề cập đến finalizers thực sự không phải là những gì bạn đang sau.

Điều tốt nhất bạn có thể làm là enqueue PhantomReference trong ReferenceQueue và cuộc thăm dò cho đến khi bạn nhận được tham chiếu.

final ReferenceQueue rq = new ReferenceQueue(); 
final PhantomReference phantom = new PhantomReference(referenceToObjectYouWantToTrack, rq); 

Bạn muốn đọc câu trả lời Peter Kofler ở đây (nó giải thích những gì một PhantomReference là):

Have you ever used Phantom reference in any project?

Rất thú vị đọc ở đây:

http://www.kdgregory.com/index.php?page=java.refobj

Về cơ bản, tôi đang sử dụng PhantomReference trong một dự án mà một loại bộ nhớ cache rất đặc biệt cần phải được tính một lần, khi phần mềm được cài đặt. Để tính toán hiệu quả bộ đệm (dựa trên đĩa) này, cần một lượng bộ nhớ khổng lồ (càng nhiều càng tốt). Tôi đang sử dụng PhantomReference để theo dõi "gần như chính xác" khi lượng bộ nhớ khổng lồ đó được giải phóng.

+0

Thông tin và liên kết tốt, có vẻ như Peter gợi ý sử dụng một hồ sơ. – Shizam

+0

Vì không có vấn đề gì mà finalizers có thể giải quyết mà PhantomReferences không thể, tôi đã cập nhật câu trả lời của mình. Tôi nghĩ rằng finalizers là "đủ tốt" cho những gì OP đang cố gắng để làm, nhưng tôi nhận ra tôi không nên khuyến khích kỹ thuật bán không được chấp nhận. –

+0

Cho đến nay các trình biên dịch tôi đã cố gắng không có độ phân giải để hiển thị nếu một đối tượng được phát hành. Có vẻ như câu trả lời này (PhantomReferences) có thể là công cụ tốt nhất nhưng tôi gặp khó khăn khi tìm một ví dụ về cách sử dụng nó để chỉ theo dõi các đối tượng được phát hành. Ví dụ tại kdgregory đang sử dụng nó để theo dõi các kết nối SQL. Chính xác những gì tôi đang bỏ phiếu cho các giá trị null, referenceQueue hoặc một số danh sách theo dõi khác? – Shizam

3

Edit:

Như NoozNooz42 đã chỉ ra, một PhantomReference có thể làm tất cả mọi thứ một finalizer có thể, mà không cần những vấn đề finalizers hiện. Vì vậy, tôi khuyến khích sử dụng PhantomReferences để mở rộng finalize(). Tôi giữ nguyên bản gốc của mình, vì tôi nghĩ rằng các lập trình viên Java nên ít nhất biết rằng finalize() tồn tại.

Original Post:

lớp Mỗi Java có một phương pháp finalize() đó được chạy khi không có đối tượng khác giữ một tham chiếu đến lớp đó. Bạn có thể mở rộng phương pháp này như sau:

protected void finalize() throws Throwable { 
    try { 
     // Do whatever you want 
    } finally { 
     super.finalize(); 
    } 
} 

Bằng cách làm như vậy, bạn có thể tìm hiểu xem có điều gì liên quan đến Đối tượng được đề cập không. Chỉ cần đảm bảo bạn luôn gọi super.finalize() nếu bạn sử dụng phương pháp này.

tham khảo về quyết toán:

http://java.sun.com/developer/technicalArticles/javase/finalization/

+2

Các trình hoàn thiện phải tránh trong Java vì chúng không đảm bảo khi các đối tượng thực sự được thu thập. Đồng thời hoàn tất chỉ hoạt động khi cá thể đủ điều kiện để thu thập. Thông thường các đối tượng có vấn đề được giữ trong bộ nhớ bởi một số cá thể khác để việc hoàn thành không giúp được gì. Xem thêm tại đây: http://my.safaribooksonline.com/0201310058/ch02lev1sec6 (Java hiệu quả bởi Josh Bloch) –

+0

@jwachter: Tốt, nhưng liên kết của bạn yêu cầu đăng nhập để đọc. –

+0

@Justin Ardini: hoàn thành sẽ xảy ra ** WAY TRƯỚC KHI ** một đối tượng là GC'ed. Xem câu trả lời của tôi: OP là sau PhantomReference, không phải finalizers. – NoozNooz42

1

Hãy thử YourKit. Đó là một hồ sơ Java có thể cho bạn thấy việc sử dụng bộ nhớ của bạn và những gì đang xảy ra. IIRC, bản dùng thử miễn phí có thể tích hợp với Eclipse và có tất cả các tính năng của phiên bản trả tiền (nó chỉ có giới hạn thời gian).

3

Có nhiều cách để phát hiện rò rỉ bộ nhớ. Ở đây, ba tôi hiện đang nghĩ đến việc:

  1. Gắn một Profiler để ứng dụng của bạn (Netbeans hoặc Eclipse TPTP nên có ích ở đây)
  2. Làm một đống đổ và phân tích (với Eclipse Memory Analyzer) những gì thể hiện của một lớp là được lưu trữ trong bộ nhớ mà các trường hợp khác.
  3. Đính kèm VisualVM để theo dõi trạng thái Thu gom rác.
+0

nhưng câu hỏi không đề cập đến bất kỳ bộ nhớ ** rò rỉ ** nào. OP chỉ muốn theo dõi khi một đối tượng là GC'ed. – NoozNooz42

+0

Thật không may # 1 đã không bao giờ làm việc cho applet của tôi, không bao giờ tìm ra lý do tại sao. Tôi sẽ kiểm tra VisualVM là tốt, hiện đang cố gắng YourKit. – Shizam

+0

@ NoozNooz42 bạn nói đúng. Nhưng tôi nghĩ bạn thường chỉ tìm kiếm khi có thứ gì đó được thu thập nếu có vấn đề về trí nhớ. –

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