Điều gì gây ra PermGen OutOfMemoryError trên JBoss?


8

Nguyên nhân cơ bản của PermGen OutOfMemoryError trong JBoss là gì?

Tôi đang chạy JBoss AS 4.2.2 trong môi trường phát triển của mình và điều này xảy ra sau khi triển khai lại ứng dụng web của tôi một số lượng lớn.

Blog của Christian Vest Hansen cung cấp các tùy chọn JVM giúp ích rất nhiều , nhưng không giải quyết được hoàn toàn vấn đề:

-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m

Câu trả lời:


5

Như đã đề cập, có lẽ bạn đang gặp phải các trình tải lớp bị rò rỉ. Vì một số lý do, các lớp học của bạn không được tải. Điều này có thể xảy ra vì hai lý do

  • Các đối tượng của các lớp đã nói vẫn tồn tại trên heap, các đối tượng luôn tham chiếu lớp của chúng hoặc
  • Trình tải lớp được tham chiếu ở đâu đó, vì bất kỳ lý do gì, trình nạp lớp tham chiếu các lớp của chúng để không tải chúng hai lần

Không có giải pháp bắt tất cả cho vấn đề này. Một công cụ hữu ích để giúp bạn tìm ra nguyên nhân gốc là Công cụ phân tích bộ nhớ Eclipse , bạn có thể áp dụng cho một đống heap từ JVM của mình (bạn có thể kích hoạt các đống heap trên các OOM với tùy chọn -XX: + HeapDumpOnOutOfMemoryError). Có lẽ bắt đầu tìm kiếm các đối tượng java.lang.Class từ ứng dụng web của bạn để xem lý do tại sao chúng được giữ sống. Thật không may, PermGen thường không phải là một phần của kết xuất heap JVM, vì vậy bạn chỉ có thể cố gắng tìm các tạo phẩm tương quan trong phần còn lại của heap (Các đối tượng lớp không được lưu trữ trong PermGen nếu tôi không nhầm, chỉ có mã byte thực tế sửa tôi nếu tôi sai mặc dù).

HTH.

Chỉnh sửa:
Dave Cheney gợi ý trong một nhận xét rằng java.lang.Class-object thực sự là một phần của PermGen và không được bao gồm trong một đống heap hotspot bình thường. Trừ khi bạn có một JVM ghi thông tin này trong vùng heap, bạn sẽ cần một cách tiếp cận khác. Bạn vẫn có thể tìm kiếm các thể hiện của các đối tượng của mình, nhưng nếu bạn rò rỉ các trình nạp lớp / lớp (cả hai đều không may ám chỉ nhau) thì có vẻ như bạn cần tìm các dấu hiệu khác (các đối tượng dữ liệu meta từ JBoss, v.v.).


1
Tôi khá chắc chắn rằng các đối tượng Class được lưu trữ trong PermGen (nghĩa là các đối tượng là các thể hiện của Class). Có một khu vực riêng biệt trên Sun JVM được gọi là Bộ đệm mã, là nơi mã được biên dịch thành mã máy được lưu trữ. Cả PermGen và Code Cache đều là một phần của bộ nhớ Non Heap mà bạn có thể thấy bằng cách sử dụng các công cụ như jconsole
Dave Cheney

@Dave Cheney: Bạn đã đúng. Các đối tượng Class bị rò rỉ bị kẹt trong PermGen thường là nguyên nhân gây ra sự cố của OP.
Eddie

roe, trong khi tôi không nghĩ rằng nội dung của PermGen được ghi vào bãi chứa heap (cái này sử dụng Sun JVM, tôi không có nhiều kinh nghiệm với những cái khác), định dạng kết xuất hprof chắc chắn biết những thứ như, bao nhiêu các lớp đã được tải, có bao nhiêu trình nạp lớp, v.v. Bạn có thể thấy điều này khi mở hprof trong Trình phân tích bộ nhớ Eclipse). Điều có lẽ không được ghi là dữ liệu lớp nhị phân lớn tạo nên mã byte java, những gì bạn thấy trong kết xuất heap là 'sơ khai' của thể hiện Class được lưu trữ trên PermGen.
Dave Cheney

2

Nguyên nhân cơ bản là các tham chiếu đến các lớp đã bị loại bỏ rò rỉ bên ngoài trình nạp lớp của chúng, ngăn JVM không tải các lớp đó khỏi gen perm. Những cờ bạn sử dụng có thể khiến JVM tích cực thanh lọc các lớp không tải được , nhưng nó sẽ không giải quyết được vấn đề tiềm ẩn.

Có một lời giải thích phức tạp, tốt ở đây


1

Nguyên nhân gây ra lỗi PermGen OutOfMemory là do các ứng dụng lại. Nguyên nhân cơ bản là các đối tượng Class bị rò rỉ trong PermGen từ các bản hợp đồng.

Tất nhiên, cách giải quyết là khởi động lại JVM sau một số lần tái cấu trúc nhất định.

Đây là một vấn đề rất khó giải quyết hoàn toàn, mặc dù với một số điều tra, bạn thường có thể thực hiện những cải tiến lớn. Đây là nơi bạn bắt đầu: Khi ứng dụng web của bạn bị dừng, hãy đảm bảo rằng:

  • tất cả các chủ đề mà bạn bắt đầu đã dừng lại
  • tất cả các ThreadPool mà bạn bắt đầu đều bị tắt
  • tất cả các tham chiếu tĩnh mà bạn có thể phát hành được phát hành

Đây là một số điều có thể khiến một đối tượng Class bị mắc kẹt trong PermGen.

Ngoài ra, lưu ý rằng không phải tất cả các JVM (hoặc tất cả các phiên bản của JVM) sẽ là các đối tượng Lớp GC trong PermGen. Nếu bạn đang chạy JVM hoặc một phiên bản của JVM sẽ không phải là các đối tượng Lớp GC trong PermGen, thì lựa chọn duy nhất của bạn là khởi động lại JVM sau một số lần tái cấu trúc nhất định. Điều này có thể không áp dụng cho bạn, với các tùy chọn JVM mà bạn đề cập.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.