2011-12-13 17 views
12

Tôi có một bãi chứa bộ nhớ mà tôi đã thực hiện từ một ứng dụng sắp chết. Nó đã tiêu thụ tất cả các đống có sẵn (-Xmx1024m). Nó sử dụng com.gargoylesoftware.htmlunit.WebClient để thu thập thông tin các trang web. Thực hiện một vài yêu cầu http mỗi phút, chết trong vài ngày. Như tôi thấy từ bãi chứa, nó có ~ 1750 bản sao của lớp HtmlPage, mỗi lớp có tông màu của các đối tượng liên quan, bao gồm nội dung đầy đủ của một trang được thu thập thông tin.Rò rỉ bộ nhớ săn bắn, VisualVM: "Không tìm thấy thư mục gốc GC". Cái gì tiếp theo?

Tôi không thể hiểu tại sao HtmlPage không phải là rác được thu thập. Tôi đã điều tra tài liệu tham khảo cá thể và tôi không thấy bất kỳ mã nào của tôi đang nắm giữ tham chiếu đến nó và VisualVM nói rằng "Không tìm thấy thư mục gốc GC". Theo tôi hiểu nó có nghĩa là đối tượng có đủ điều kiện cho gc, nhưng nó không hoạt động.

Ứng dụng đang chạy như một quá trình độc lập đơn giản, nó không sử dụng bất kỳ vùng chứa web hoặc máy chủ ứng dụng nào.

Bất kỳ gợi ý? Tôi nên xem xét điều gì khác?

Specs:

  • HtmlUnit v2.7
  • phiên bản java "1.6.0_13" Java (TM) SE Runtime Environment (xây dựng 1.6.0_13-b03) Java HotSpot (TM) Máy chủ VM (xây dựng 11.3-b02, chế độ hỗn hợp)
  • Linux my.lan 2.6.18-128.el5 # 1 SMP Thứ tư ngày 17 tháng 12 11:42:39 EST 2008 i686 i686 i386 GNU/Linux

Update1

Tôi đã cố gắng để phân tích các bãi chứa của YourKit Java Profiler. Nó cho tôi thấy rất nhiều đối tượng java.lang.ref.Finalizer với kích thước giữ lại 310mb. Chúng được tạo cho trình hoàn tất net.sourceforge.htmlunit.corejs.javascript.NativeGenerator#finalize()NativeGenerator đề cập đến Window, sau đó đến HtmlPage và cho mọi thứ.

Có ai biết tại sao họ ở lại trong bộ nhớ?

Lưu ý: Tò mò, nhưng VisualVM đã hiển thị "đang chờ hoàn tất" là không.

+0

Bạn đã sử dụng đối số dòng lệnh cụ thể cho JVM chưa? –

+0

@ThomasJungblut '-Xmx1024m -XX: MaxPermSize = 128m -XX: + PrintGCDetails -XX: + PrintGCTimeStamps -XX: + UseConcMarkSweepGC' – kan

+0

Tôi cũng gặp phải rò rỉ bộ nhớ với htmlunit 2.8. Như một giải pháp thay thế, tôi tái khởi tạo WebClient một lần một ngày. Hy vọng bạn có thể theo dõi lỗi này. – milan

Trả lời

1

Hãy chắc chắn rằng bạn đang gọi điện thoại webClient.closeAllWindows() sau khi bạn đã hoàn tất với trang (s) - nếu không đề Javascript đang tiếp tục chạy tài liệu tham khảo giữ đến tài nguyên trang, vv

+1

tôi đã' setJavaScriptEnabled (sai) '. Cố gắng thực hiện một thử nghiệm nhỏ và có vẻ như nó hoạt động tốt ngay cả khi không có 'closeAllWindows'. Nhưng tôi tiếp tục cố gắng ... – kan

+0

Tôi đã nghĩ rằng chỉ có lý do để thu thập thông tin với XmlUnit là có thể sử dụng JavaScript trên các trang. Oh well;) – maximdim

+0

Một số trang khác (thu thập dữ liệu trong các quy trình khác nhau) sử dụng javascript, tuy nhiên ứng dụng cụ thể này không cần đến, nhưng thu thập thông tin thường xuyên hơn. – kan

1

Khi một đối tượng có không phương thức finalize() tầm thường, khi tạo một thể hiện của đối tượng mà JVM tạo ra java.lang.ref.Finalizer giữ tham chiếu đến đối tượng đã tạo để nó không thu gom rác trước khi phương thức finalize() kết thúc. Rò rỉ bộ nhớ xuất phát từ những java.lang.ref.Finalizer-s không bị xóa theo thời gian. Thanh toán bù trừ của các finalizers được thực hiện bởi một thread daemon finalizer riêng biệt có ưu tiên thấp hơn, vì vậy nếu bạn tạo ra rất nhiều trường hợp của các đối tượng với phương thức finalize() đã thực hiện, trong thời gian bạn hết bộ nhớ.

của tất cả các mô tả rất tốt trong:

http://www.fasterj.com/articles/finalizer2.shtml

Đây là họ đề nghị những gì như một giải pháp:

"Một cách rõ ràng là để tăng độ ưu tiên của 'finalizer' daemon thread - không có API cho điều này, vì vậy bạn phải chạy qua tất cả các chủ đề để tìm nó theo tên, sau đó tăng ưu tiên của nó. "

Chúc may mắn

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