2010-07-26 18 views
168

Tôi không thể cho cuộc sống của tôi tìm thấy định nghĩa về cờ Java VM CMSClassUnloadingEnabled thực sự, ngoại trừ một số định nghĩa cấp cao rất mờ như "loại bỏ các vấn đề PermGen của bạn" (which it doesn't, btw).JVM flag CMSClassUnloadingEnabled thực sự làm gì?

Tôi đã xem trên trang web của Sun/Oracle và thậm chí cả the options list không thực sự nói nó hoạt động như thế nào.

Dựa trên tên của lá cờ, tôi đoán rằng Trình thu thập dữ liệu CMS không theo các lớp dỡ hàng mặc định và cờ này bật lên - nhưng tôi không chắc chắn.

Trả lời

201

Cập nhật Câu trả lời này là có liên quan cho Java 5-7, Java 8 có này cố định: https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace Kudos đi đến mt.uulu

Đối với Java 5-7:

Tiêu chuẩn Oracle/Sun VM nhìn thế giới là: Lớp học là mãi mãi. Vì vậy, một khi được nạp, họ sẽ ở trong bộ nhớ ngay cả khi không ai quan tâm nữa. Điều này thường không có vấn đề vì bạn không có nhiều lớp "setup" thuần túy (= được sử dụng một lần để thiết lập và sau đó không bao giờ trở lại). Vì vậy, ngay cả khi họ mất 1MB, những người quan tâm.

Nhưng gần đây, chúng tôi có các ngôn ngữ như Groovy, xác định các lớp khi chạy. Mỗi lần bạn chạy một tập lệnh, một (hoặc nhiều) lớp mới được tạo và chúng vẫn ở trong PermGen mãi mãi. Nếu bạn đang chạy một máy chủ, điều đó có nghĩa là bạn bị rò rỉ bộ nhớ.

Nếu bạn bật CMSClassUnloadingEnabled, GC cũng sẽ quét PermGen và xóa các lớp không còn được sử dụng nữa.

[EDIT] Bạn cũng sẽ phải bật UseConcMarkSweepGC (nhờ Sam Hasler). Xem câu trả lời này: https://stackoverflow.com/a/3720052/2541

+15

Theo http://stackoverflow.com/a/3720052/2541 cho 'CMSClassUnloadingEnabled' có bất kỳ tác động nào, 'UseConcMarkSweepGC' cũng phải được đặt –

+1

Không chắc chắn điều này ảnh hưởng đến ý tưởng sử dụng UseConcatSweepGC như thế nào, nhưng có vẻ như đã có lỗi gần đây đã được sửa trong CMSClassUnloadingEnabled. Nó được coi là cố định ở đây: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8000325 – BillR

+0

Đối với các ngôn ngữ như Groovy tự động xác định các lớp học, có thực hành tốt để cho phép cờ này làm sạch định kỳ PermGen không? –

34

Theo bài đăng trên blog The most complete list of -XX options for Java JVM, nó xác định xem việc nạp lớp có được bật trong trình thu gom rác CMS hay không. Giá trị mặc định là false. Có một tùy chọn khác được gọi là ClassUnloading theo mặc định là true mà (có lẽ) ảnh hưởng đến các bộ thu gom rác khác. Ý tưởng là nếu GC phát hiện rằng một lớp được tải trước đó không còn được sử dụng ở bất kỳ đâu trong JVM, nó có thể đòi lại bộ nhớ được sử dụng để giữ các lớp bytecode và/hoặc mã gốc.

Đặt CMSClassUnloadingEnabled có thể trợ giúp với sự cố permgen của bạn nếu bạn hiện đang sử dụng bộ thu CMS. Nhưng cơ hội là bạn không sử dụng CMS, hoặc bạn bị rò rỉ bộ nhớ liên quan đến bộ nạp lớp chính hãng. Trong trường hợp sau, lớp học của bạn sẽ không bao giờ xuất hiện với GC sẽ không được sử dụng ... và do đó sẽ không bao giờ được dỡ xuống.


Aaron Digulla nói "các lớp học luôn luôn". Điều này không đúng, ngay cả trong thế giới thuần túy Java. Trong thực tế, tuổi thọ của một lớp được gắn với trình nạp lớp của nó. Vì vậy, nếu bạn có thể sắp xếp rằng một bộ nạp lớp là rác được thu thập (và đó không phải lúc nào cũng dễ dàng làm) các lớp mà nó nạp cũng sẽ được thu gom rác.

Thực tế, đây là những gì sẽ xảy ra khi bạn thực hiện triển khai lại ứng dụng web. (Hoặc ít nhất, đó là những gì sẽ xảy ra, nếu bạn có thể tránh được những vấn đề dẫn đến rò rỉ lưu trữ permgen.)

22

Một ví dụ nơi này rất hữu ích:

Thiết -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled trên WebLogic 10,3 JVM của chúng tôi đã giúp giải quyết một vấn đề mà thực hiện JAX-WS đã tạo ra một lớp proxy mới cho mỗi cuộc gọi dịch vụ web, cuối cùng dẫn đến ra khỏi bộ nhớ lỗi.

Nó không tầm thường để theo dõi. Các mã sau đây luôn luôn trở lại lớp proxy tương tự cho port

final MyPortType port = 
Service.create(
     getClass().getResource("/path/to.wsdl"), 
     new QName("http://www.example.com", "MyService")) 
    .getPort(
     new QName("http://www.example.com", "MyPortType"), 
     MyPortType.class); 

Bên trong, proxy này giao cho một thể hiện của weblogic.wsee.jaxws.spi.ClientInstance, mà lại giao cho một lớp học mới $Proxy[nnnn] nơi n được tăng lên ở mọi cuộc gọi. Khi thêm cờ, n vẫn được tăng lên, nhưng ít nhất các lớp tạm thời đó đã bị xóa khỏi bộ nhớ.

Trên một lưu ý tổng quát hơn, điều này có thể rất hữu ích khi tận dụng nặng của Java phản ánh và proxy thông qua java.lang.reflect.Proxy

+0

+1 để chia sẻ trải nghiệm thực tế. Chúng tôi cũng đã có vấn đề này trên torquebox nơi máy chủ tạo ra một số lượng lớn các lớp học do quá trình biên dịch JRuby. – nurettin

+7

cũng lưu ý rằng '-XX: + CMSPermGenSweepingEnabled' không được hỗ trợ cho' -XX: + CMSClassUnloadingEnabled' – nurettin

+0

@nurettin: Rất vui được biết, cảm ơn thông tin –