簡體   English   中英

如何模擬 OutOfMemoryError: Metaspace

[英]How to simulate OutOfMemoryError: Metaspace

我想知道如何自己導致 OutOfMemoryError: Metaspace 異常? 是否可以加載很多類並讓它們在內存中停留很長時間。

繼續向StringBuilder添加一些文本,直到出現OutOfMemoryError

StringBuilder s = new StringBuilder();

while (true) {
    s.append("dummy");
}

您還可以將一些虛擬類添加到ListSet ,但創建新實例更耗時,您必須等待一段時間才能獲得OutOfMemoryError

插入數組列表的攤銷時間成本也會有所不同。

更新

默認情況下,Java 8 對 Metaspace 的最大大小沒有限制,因此只要您不使用MaxMetaspaceSize標志設置限制,就不應該拋出錯誤。

要創建OutOfMemoryError: Metaspace使用javassist.ClassPool庫。 下面的示例將創建元Metaspace錯誤。

import javassist.ClassPool;

public class OutOfMemoryErrorMetaspace {

    //ClassPool objects hold all the CtClasses.
    static ClassPool classPool = ClassPool.getDefault();

    public static void main(String[] args) throws Exception {
           for (int i = 0; i < 1000000; i++) {
                  //makeClass method - Creates a new class (or interface) from the given class file.
                  Class clas = classPool.makeClass(
                               i + " outofmemory.OutOfMemoryErrorMetaspace ").toClass();
                  //Print name of class loaded
                  System.out.println(clas.getName());
           }
    }
}

為了模擬java.lang.OutOfMemoryError: Metaspace ,你必須加載很多不同的類。

首先必須設置以下元空間設置:

-XX:MaxMetaspaceSize=10m
-XX:MetaspaceSize=2M
-XX:MaxMetaspaceFreeRatio=1
-XX:MaxMetaspaceExpansion=1K
-XX:MinMetaspaceFreeRatio=1
-XX:InitialBootClassLoaderMetaspaceSize=2M

然后下面的代碼讓類加載器加載了很多不同的類。 這是通過獲取類mypackage.Myclass0的編譯字節碼並通過更改類名和調整類名的長度調整以迭代地創建新類來實現的:

    public static void main(String[] args) throws Exception {
        String clazzBase64 ="yv66vgAAADcADAEAEm15cGFja2FnZS9NeWNsYXNzMAcAAQEAEGphdmEvbGFuZy9PYmplY3QHAAMBAApTb3VyY2VGaWxlAQANTXljbGFzczAuamF2YQEABjxpbml0PgEAAygpVgwABwAICgAEAAkBAARDb2RlACEAAgAEAAAAAAABAAEABwAIAAEACwAAABEAAQABAAAABSq3AAqxAAAAAAABAAUAAAACAAY=";

        byte[] compiledClazz = Base64.getDecoder().decode(clazzBase64);
        int classNameLength = Integer.valueOf(compiledClazz[12]);

        MyClassLoader myClassLoader = new MyClassLoader(Thread.currentThread().getContextClassLoader());

        for (int i = 0; ; i++) {
            byte[] bytes = String.valueOf(i).getBytes();
            byte[] bytecode = new byte[compiledClazz.length + bytes.length - 1];
            System.arraycopy(compiledClazz, 0, bytecode, 0, 30);
            bytecode[12] = (byte) (classNameLength + bytes.length - 1 & 0xFF);

            System.arraycopy(bytes, 0, bytecode, 30, bytes.length);
            System.arraycopy(compiledClazz, 31, bytecode, 30 + bytes.length, compiledClazz.length - 31);

            String classname = "mypackage.Myclass" + i;
            Class c = myClassLoader.getClass(classname, bytecode);
        }
    }

    public static class MyClassLoader extends ClassLoader {
        public MyClassLoader(ClassLoader parent) {
            super(parent);
        }

        public Class<?> getClass(String name, byte[] code) {
            return defineClass(name, code, 0, code.length);
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM