2010-06-02 29 views
10

Trong hầu hết tất cả các dự án Java lớn hơn mà tôi đã tham gia, tôi nhận thấy rằng chất lượng dịch vụ của ứng dụng sẽ giảm đi theo thời gian hoạt động của vùng chứa. Điều này có lẽ là do rò rỉ bộ nhớ trong mã.Thực hành tốt nhất để xử lý rò rỉ bộ nhớ trong các dự án Java lớn?

Cách chính xác để giải quyết vấn đề này rõ ràng là truy nguyên ngược lại nguyên nhân gốc rễ của sự cố và khắc phục sự cố rò rỉ trong mã. Cách nhanh chóng và dơ bẩn để giải quyết vấn đề đơn giản là khởi động lại Tomcat (hoặc bất cứ thùng chứa servlet nào bạn đang sử dụng).

Đây là ba câu hỏi của tôi:

  • Giả sử rằng bạn chọn để giải quyết vấn đề bằng cách truy tìm nguyên nhân gốc rễ của vấn đề (các rò rỉ bộ nhớ), làm thế nào bạn sẽ thu thập dữ liệu để phóng to trên các vấn đề ?

  • Giả sử bạn chọn cách tăng tốc nhanh chóng và bẩn thỉu bằng cách khởi động lại vùng chứa, cách bạn thu thập dữ liệu để chọn chu kỳ khởi động lại tối ưu?

  • Bạn đã có thể triển khai và chạy các dự án trong một khoảng thời gian dài mà không cần phải khởi động lại thùng chứa servlet để lấy lại sự mất ổn định? Hoặc là một servlet thường xuyên khởi động lại một cái gì đó mà người ta phải đơn giản chấp nhận?

Trả lời

9

Giả sử bạn chọn giải quyết vấn đề bằng cách truy tìm nguyên nhân gốc của sự cố (rò rỉ bộ nhớ), bạn thu thập dữ liệu để phóng to vấn đề như thế nào?

Lấy thùng chứa bằng cách sử dụng jmap và tải kết xuất bằng cách sử dụng Eclipse Memory Analyzer. Từ đó bạn có thể phân tích đối tượng nào đang ăn nhiều bộ nhớ nhất, mà "rễ" đang ngăn không cho các đối tượng khác được thu thập, v.v.

Có các chương trình phân tích heap khác, chẳng hạn như jhat, nhưng tôi đã tìm thấy EMA là giải pháp nhanh nhất và tốt nhất (miễn phí).

Giả sử bạn chọn cách nhanh chóng và bẩn để tăng tốc mọi thứ bằng cách khởi động lại vùng chứa, cách bạn thu thập dữ liệu để chọn chu kỳ khởi động lại tối ưu?

Sử dụng JMX để theo dõi kích thước heap và thống kê heap và GC khác.

Bạn đã có thể triển khai và chạy các dự án trong một khoảng thời gian dài mà không bao giờ khởi động lại thùng chứa servlet để lấy lại sự mất ổn định?

Có. Bằng cách tránh/sửa lỗi rò rỉ bộ nhớ.

+1

+1 cho câu trả lời đơn giản, vô nghĩa. Việc khởi động lại vùng chứa là một công việc đơn giản, nhưng không phải là giải pháp lâu dài. Tự động hóa việc khởi động lại vùng chứa là một công việc tự động, có một số lợi ích của một giải pháp, nhưng cũng có rất nhiều nhược điểm. –

1

Lý tưởng nhất, bạn không cần phải khởi động lại chương trình hoặc servlet của mình.

Kinh nghiệm của tôi là hầu hết các nguyên nhân gây ra sự cố bộ nhớ thường là do sự cố trong phân bổ hoặc gộp chung một nhóm nhỏ các lớp.

Một công cụ như VisualVM là điều tuyệt vời cho điều đó, vì bạn có thể tìm ra vị trí đặt gánh nặng của phân bổ đối tượng của bạn.

Nó có thể là một chút phức tạp hơn với tomcat vì bạn cũng sẽ theo dõi khuôn khổ, nhưng với sự chăm sóc và kiên nhẫn đầy đủ, bạn thường có thể xác định các điểm nóng trong logic của bạn.

2

Có một số công cụ lược tả tuyệt vời ngoài kia. Học cách sử dụng thường xuyên và hiểu đầu ra phân bổ bộ nhớ.

Về cơ bản bạn làm theo quá trình này đối với từng chức năng quan trọng của ứng dụng của bạn:

  • Chạy qua quá trình này một lần
  • GC hai lần
  • Đánh đếm phân bổ hiện tại của bạn cho tất cả các đối tượng
  • chạy qua của bạn xử lý lại
  • GC hai lần
  • Đánh dấu lại
  • Khác biệt hai nhãn hiệu

Nếu chúng không quá gần, bạn có thể bị rò rỉ.

Nếu bất kỳ số lượng đối tượng nào tăng theo một số tiền nhất định mỗi lần lặp lại quy trình này thì bạn hoàn toàn bị rò rỉ.

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