2014-10-19 15 views
15

tôi có mã này để tạo lớp tự động và tải nóJava8 metaspace & đống sử dụng

import javassist.CannotCompileException; 
import javassist.ClassPool; 

public class PermGenLeak { 
    private static final String PACKAGE_NAME = "com.jigarjoshi.permgenleak."; 

    public static void main(String[] args) throws CannotCompileException, InterruptedException { 
     for (int i = 0; i < Integer.MAX_VALUE; i++) { 
      ClassPool pool = ClassPool.getDefault(); 
      pool.makeClass(PACKAGE_NAME + i).toClass(); 
      Thread.sleep(3); 
     } 

    } 
} 

tôi đưa ra lớp này chống lại Java 7 (jdk1.7.0_60) và như mong đợi nó lấp đầy PermGenSpace và đống vẫn chưa sử dụng Java 7 memory usage hình ảnh cho thấy PermGen thêm giờ sử dụng và tại các JVM cuối đã được chấm dứt

Bây giờ cùng mã chạy chống Java 8 (jdk1.8.0_40-ea) và như mong đợi nó giữ mở rộng bộ nhớ quê hương (Metaspace) nhưng đáng ngạc nhiên cho 1g Metaspace tiêu thụ 3g Heap trong OldGen (almos t 3x của Metaspace duy trì theo thời gian)

Java8 memory usage hình ảnh cho thấy việc sử dụng Metaspace thêm giờ và hệ thống mẫu sử dụng bộ nhớ

this email from Jon Masamitsuthis JEP ticket nói

thực tập nội trú String và lớp số liệu thống kê và một số dữ liệu misc có đã được chuyển đến Heap

chính xác những gì làm cho sự gia tăng này trong đống như nó tải thêm các lớp học vào Metaspace?

Trả lời

10

Chạy jmap -histo PID để xem đối tượng nào tiêu thụ Không gian Heap.
Khi tôi chạy ví dụ của bạn tôi thấy đống đầy Javassist vật phụ:

num  #instances   #bytes class name 
---------------------------------------------- 
    1:  592309  312739152 [Ljavassist.bytecode.ConstInfo; 
    2:  6515673  208501536 java.util.HashMap$Node 
    3:  2964403  169188824 [C 
    4:  1777622  102165184 [Ljava.lang.Object; 
    5:  4146200  99508800 javassist.bytecode.Utf8Info 
    6:  3553889  85293336 java.util.ArrayList 
    7:  2964371  71144904 java.lang.String 
    8:  593075  56944008 java.lang.Class 
    9:  592332  47388032 [Ljava.util.HashMap$Node; 
    10:  592309  37907776 javassist.bytecode.ClassFile 
    11:  592308  37907712 javassist.CtNewClass 
    12:  1185118  28555808 [B 
    13:  592342  28432416 java.util.HashMap 
    14:  1184624  28430976 javassist.bytecode.ClassInfo 
    15:  592309  28430832 [[Ljavassist.bytecode.ConstInfo; 
    16:  592322  23692880 javassist.bytecode.MethodInfo 
    17:  592315  23692600 javassist.bytecode.CodeAttribute 
    18:  592434  18957888 java.util.Hashtable$Entry 
    19:  592309  18953888 javassist.bytecode.ConstPool 
    20:  592308  18953856 java.lang.ref.WeakReference 
    21:  592318  14215632 javassist.bytecode.MethodrefInfo 
    22:  592318  14215632 javassist.bytecode.NameAndTypeInfo 
    23:  592315  14215560 javassist.bytecode.ExceptionTable 
    24:  592309  14215416 javassist.bytecode.LongVector 
    25:  592309  14215416 javassist.bytecode.SourceFileAttribute 
    26:  592507  9487584 [I 
    27:    8  6292528 [Ljava.util.Hashtable$Entry; 
    28:   212   18656 java.lang.reflect.Method 
    29:   407   13024 java.util.concurrent.ConcurrentHashMap$Node 
    30:   124   8928 java.lang.reflect.Field 
+0

Cảm ơn Andrei, tôi nên đã thực hiện điều này, tôi nghĩ rằng tôi đã không đạt được ở quy mô này trong ví dụ Java 7 đó là lý do tại sao tôi đã không nhìn thấy nó trong Java 7 –

3

chính xác điều gì làm tăng mức tăng này khi tải nhiều lớp hơn vào Metaspace?

Giả thuyết của tôi là đây là rác "bình thường" đang được tạo bởi ví dụ của bạn. Tôi phỏng đoán rằng:

  • javaassist tạo đối tượng heap thông thường. Chúng chủ yếu là "lớn" và khiến chúng được phân bổ trực tiếp vào đống OldGen. Hoặc cái gì khác gây ra điều đó.

    (CẬP NHẬT - nhìn @ apangin của trả lời, bây giờ tôi nghi ngờ rằng họ bắt đầu ra trong đống YoungGen và được gạo cội ...)

  • Khi classLoader.defineClass được gọi dưới mui xe, nó tạo ra các đối tượng trong metaspace từ mảng byte chứa classfile.

  • Việc sử dụng OldGen vẫn còn ... vì không có gì kích hoạt GC đầy đủ.

Nếu bạn chỉnh sửa ví dụ để lớp học có thể truy cập được, sau đó buộc GC đầy đủ, tôi mong đợi (xem) sử dụng OldHeap để giảm, cho biết rằng đó là rác "thông thường" thay vì rò rỉ bộ nhớ.

+0

Cảm ơn Stephen, Nó hoàn toàn có ý nghĩa bây giờ, tôi nghĩ rằng tôi đã không đạt được ở quy mô này phân bổ trong Java 7 ví dụ đó là tại sao tôi không nhìn thấy nó trong Java 7 –

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