如何创建 java.lang.OutOfMemoryError: Metaspace?

huangapple go评论79阅读模式
英文:

How to create java.lang.OutOfMemoryError: Metaspace?

问题

我想模拟一个情况,在这种情况下我可以收到这个错误。
我曾经尝试过在 https://stackoverflow.com/questions/52661753/how-to-simulate-outofmemoryerror-metaspace 上进行过,但是没有帮助。

我在配置中设置了:
-XX:MaxMetaspaceSize=50m

尝试过以下方法:

public class Main {
    public static void main(String[] args) {
        for (int i = 0; ; i++) {
            Thread thread = new Thread(new A());
            thread.start();
        }
    }
}

还有这个:
A 和 B 的 POJO 类

public class Main {
    static Map<A, B> map = new LinkedHashMap<>();
    public static void main(String[] args) {
        while (true) {
            A a = new A();
            B b = new B();
            map.put(a, b);
        }
    }
}
英文:

My goal is to simulate a situation in which I can receive this error.
I had tried it https://stackoverflow.com/questions/52661753/how-to-simulate-outofmemoryerror-metaspace
but it didn't help.

I set in config:
-XX:MaxMetaspaceSize=50m

Have tried it:

public class Main {
    public static void main(String[] args) {
        for (int i = 0; ; i++) {
            Thread thread = new Thread(new A());
            thread.start();
        }
    }
}

and it:
A and B POJO classes

public class Main {
    static Map&lt;A,B&gt; map = new LinkedHashMap&lt;&gt;();
    public static void main(String[] args) {
        while (true){
            A a = new A();
            B b = new B();
           map.put(a,b);
        }
    }
}

答案1

得分: 3

如您所述,您希望抛出 java.lang.OutOfMemoryError: Metaspace 错误。为了实现这一目标,您需要加载大量不同的类。可以通过使用 javaassist 来完成:

static javassist.ClassPool cp = javassist.ClassPool.getDefault();

public static void main(String[] args) throws Exception {
    for (int i = 0; ; i++) {
        Class c = cp.makeClass("mypackage.Myclass" + i).toClass();
    }
}

并配以以下 Metaspace 设置:

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

如果没有使用 javaassist,您可以通过保持相同的 Metaspace 选项来生成 java.lang.OutOfMemoryError: Metaspace 错误:

String clazzBase64 = "..."; // Base64-encoded class bytecode
byte[] compiledClazz = Base64.getDecoder().decode(clazzBase64);
int len = 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)(len + 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);
    }
}
英文:

as you mentioned you want a java.lang.OutOfMemoryError: Metaspace to be thrown.
In order to achieve this, you have to load a lot of different classes. This can be accomplished by utilizing javaassist:

   static javassist.ClassPool cp = javassist.ClassPool.getDefault();
  
    public static void main(String[] args) throws Exception{
        for (int i = 0; ; i++) {
            Class c = cp.makeClass(&quot;mypackage.Myclass&quot; + i).toClass();
        }
    }

with following metaspace settings:

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

without javaassist, it is possible to generate java.lang.OutOfMemoryEror: Metaspace keeping the same metaspace options as follows:

            String clazzBase64 = &quot;yv66vgAAADcADAEAEm15cGFja2FnZS9NeWNsYXNzMAcAAQEAEGphdmEvbGFuZy9PYmplY3QHAAMBAApTb3VyY2VGaWxlAQANTXljbGFzczAuamF2YQEABjxpbml0PgEAAygpVgwABwAICgAEAAkBAARDb2RlACEAAgAEAAAAAAABAAEABwAIAAEACwAAABEAAQABAAAABSq3AAqxAAAAAAABAAUAAAACAAY=&quot;;
            byte[] compiledClazz = Base64.getDecoder().decode(clazzBase64);
            int len = 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)( len + bytes.length - 1 &amp; 0xFF);

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

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

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

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

huangapple
  • 本文由 发表于 2020年4月4日 01:47:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/61017610.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定