2010-03-24 61 views
17

Chúng tôi đã gặp phải lỗi Out of Memory trong máy chủ ứng dụng của chúng tôi đôi khi. Chúng tôi thấy kích thước heap đã sử dụng tăng dần cho đến khi cuối cùng nó đạt đến kích thước heap có sẵn. Điều này xảy ra sau mỗi 3 tuần, sau đó khởi động lại máy chủ là cần thiết để sửa lỗi này. Khi phân tích các vùng đống, chúng tôi thấy vấn đề là đối tượng được sử dụng trong JSP.Cách giải phóng bộ nhớ?

Các đối tượng JSP có thể là nguyên nhân thực sự của vấn đề bộ nhớ Appserver không? Làm thế nào để chúng tôi giải phóng các đối tượng JSP (Các đối tượng đang được khởi tạo bằng cách sử dụng các thẻ usebean hoặc các thẻ khác)?

Chúng tôi có một máy chủ ứng dụng Websphere được nhóm với 2 nút và IHS.

EDIT: Những phát hiện trên đây dựa trên heap-dump và nativestderr đăng nhập phân tích đưa ra dưới đây sử dụng sự hỗ trợ trợ IBM

nativestd sai lầm log phân tích:

alt text http://saregos.com/wp-content/uploads/2010/03/chart.jpg

phân tích bãi Heap:

! [Alt văn bản] [2]

Phân tích kết xuất phân tích cho thấy người thống trị ngay lập tức (2 mức tăng của nhập hastable trong hình trên)

! [alt text] [3]

Những hình ảnh cuối cùng cho thấy Dominator trước mắt là trong các đối tượng thực tế được sử dụng trong JSP.

EDIT2: Thông tin thêm có sẵn tại http://saregos.com/?p=43

+1

Tôi nhớ lại một vấn đề rò rỉ bộ nhớ cũ liên quan đến việc triển khai của JSP chưa được biên dịch trước. Trình biên dịch mặt trời đã bị rò rỉ bộ nhớ, các JSP đã được biên dịch trên bay khi chúng được tham chiếu này cuối cùng gây ra một lỗi bộ nhớ. Giải pháp là biên dịch trước JSP trước khi triển khai. – crowne

+0

nhưng trong trường hợp của chúng tôi sự cạn kiệt đống là dần dần .. bộ nhớ hết trong 3 tuần. Nó không có vẻ giống như một vấn đề biên dịch trước. Bên cạnh đó chúng tôi làm biên dịch trước các JSP của chúng tôi – sarego

+0

3 tuần - không có vấn đề gì được thực hiện trong ứng dụng? Bạn có sử dụng bất kỳ công cụ hẹn giờ nào liên quan không? Âm thanh như một hành động định kỳ không được phát hành đúng cách. –

Trả lời

7

Triggering bộ sưu tập rác bằng tay không giải quyết vấn đề của bạn - nó sẽ không tài nguyên miễn phí mà vẫn được sử dụng.

Bạn nên sử dụng công cụ lược tả (như jProfiler) để tìm rò rỉ của mình. Bạn có thể sử dụng mã có thể lưu trữ các tham chiếu trong các danh sách hoặc các bản đồ không được phát hành trong thời gian chạy - các tham chiếu tĩnh có thể đẩy được.

1

Không có cụ thể để giải phóng các đối tượng được phân bổ trong JSP, ít nhất là theo như tôi biết. Thay vì điều tra các lựa chọn như vậy, tôi muốn tập trung vào việc tìm ra vấn đề thực tế trong mã ứng dụng của bạn và sửa nó.

Một số gợi ý có thể giúp:

  • Kiểm tra phạm vi của đậu của bạn. Không phải là , ví dụ: lưu trữ một số người dùng hoặc yêu cầu cụ thể vào "ứng dụng" phạm vi (do nhầm lẫn)?
  • Kiểm tra cài đặt thời gian chờ của phiên web trong ứng dụng web của bạn và cài đặt máy chủ ứng dụng.
  • Bạn đã đề cập đến mức tiêu thụ heap tăng dần. Nếu nó thực sự như vậy, cố gắng xem kích thước heap phát triển với nhiều trường hợp người dùng khác nhau: Lấy một đống, chạy thử nghiệm, để thời gian chờ dữ liệu phiên , lấy một đoạn mã khác là .Điều đó có thể cung cấp cho bạn một số ý tưởng nơi nào các đối tượng trên heap đến từ
  • Kiểm tra đậu của bạn cho bất kỳ rò rỉ bộ nhớ rõ ràng, chắc chắn :)

EDIT: Kiểm tra các tài nguyên tĩnh chưa được phát hành mà Daniel nhắc đến là một đáng giá điều :)

8

Lần đầu tiên tôi đính kèm công cụ tiểu sử để cho bạn biết những "đối tượng" đang chiếm hết bộ nhớ.

Eclipse có TPTP, hoặc có JProfiler hoặc JProbe.

Bất kỳ nội dung nào trong số này sẽ hiển thị vùng heap của đối tượng và cho phép bạn kiểm tra để xem những gì có trên heap.

Sau đó, tìm kiếm cơ sở mã để tìm người đang tạo các mã này.

Có thể bạn có bộ nhớ cache hoặc đối tượng cây/bản đồ với các phần tử và bạn chỉ thực hiện phương thức "equals()" trên các đối tượng này và bạn cần triển khai "hashcode()". Điều này sẽ khiến bản đồ/bộ nhớ cache/cây ngày càng lớn hơn cho đến khi nó rơi xuống. Đây chỉ là một đoán mặc dù.

JProfiler sẽ là cuộc gọi đầu tiên của tôi

JavaWorld có ví dụ ảnh chụp màn hình của những gì có trong bộ nhớ ...

alt text http://www.javaworld.com/javaworld/jw-08-2003/images/jw-0822-profiler16.gif

Và một ảnh chụp màn hình của tòa nhà đối tượng đống lên và được dọn dẹp (do đó cưa cạnh)

alt text http://www.javaworld.com/javaworld/jw-08-2003/images/jw-0822-profiler19.gif

CẬP NHẬT ****************************** *******************

Ok, tôi muốn nhìn vào ...

http://www-01.ibm.com/support/docview.wss?uid=swg1PK38940

sử dụng Heap tăng theo thời gian dẫn đến một điều kiện OutOfMemory . Phân tích của một heapdump cho thấy đối tượng sau đây được chiếm một số lượng ngày càng tăng của không gian:

40.543.128 [304] 47 lớp

com/ibm/wsspi/rasdiag/DiagnosticConfigHome 40.539.056 [56] 2 java/util/Hashtable 0xa8089170 40.539.000 [2064] 511 mảng của java/util/Hashtable $ nhập 6.300.888 [40] 3 java/util/Hashtable $ HashtableCacheHashEntry

+0

Tôi đã phân tích heapdumps, coredumps và nhật ký nativestderr và có danh sách các đối tượng. Tuy nhiên vấn đề là làm thế nào để đi về sửa chữa vấn đề ... – sarego

+0

hình ảnh gắn liền với các qn ... – sarego

+0

wow kích thước heap đẹp! :-) Ok, tôi sẽ tìm kiếm JSP cho bất kỳ bản đồ/băm/treemaps nào. Tôi sẽ đoán rằng một nơi nào đó đang đưa đối tượng vào một băm bằng khóa String và khóa đó không phải là unquie đủ. Hoặc đối tượng là khóa không có phương thức equals và hashcode được triển khai. –

2

Nếu bạn chạy dưới mặt trời 6 JVM mạnh mẽ xem xét để sử dụng jvisualvm chương trình trong JDK để có được cái nhìn tổng quát về những gì thực sự diễn ra bên trong chương trình. Việc so sánh ảnh chụp thực sự tốt để giúp bạn tiếp tục trong đó các đối tượng lẻn vào.

Nếu Sun 6 JVM không phải là một tùy chọn, sau đó điều tra công cụ định dạng nào bạn có. Thử nghiệm có thể giúp bạn thực sự xa vời.

Nó có thể đơn giản như mảng ký tự khổng lồ bên dưới chuỗi con bạn đang thu thập trong danh sách, ví dụ: vệ sinh.

2

Tôi khuyên bạn nên đọc Effective Java, chapter 2. Theo dõi nó, cùng với một hồ sơ, sẽ giúp bạn xác định những nơi mà ứng dụng của bạn tạo ra rò rỉ bộ nhớ.

Giải phóng bộ nhớ không phải là cách để giải quyết mức tiêu thụ bộ nhớ mở rộng. Mức tiêu thụ bộ nhớ mở rộng có thể là kết quả của hai điều:

  • không viết mã đúng cách, để nó không tiêu thụ nhiều hơn mức cần thiết - Hiệu quả Java sẽ trợ giúp ở đây.
  • ứng dụng chỉ cần nhiều bộ nhớ này. Sau đó, bạn nên tăng bộ nhớ ảo sử dụng Xmx, Xms, XX:MaxHeapSize ...
0

Theo tôi được biết những top-level bộ nhớ ăn là lưu trữ bộ nhớ cache và các đối tượng được lưu trữ trong đó. Có lẽ bạn nên chắc chắn rằng bộ nhớ cache của bạn là đi đến các đối tượng miễn phí khi nó mất quá nhiều bộ nhớ. Bạn có thể muốn sử dụng yếu-ref nếu bạn cần bộ nhớ cache cho các đối tượng trực tiếp mà thôi.

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