英文:
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<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);
}
}
}
答案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("mypackage.Myclass" + 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 = "yv66vgAAADcADAEAEm15cGFja2FnZS9NeWNsYXNzMAcAAQEAEGphdmEvbGFuZy9PYmplY3QHAAMBAApTb3VyY2VGaWxlAQANTXljbGFzczAuamF2YQEABjxpbml0PgEAAygpVgwABwAICgAEAAkBAARDb2RlACEAAgAEAAAAAAABAAEABwAIAAEACwAAABEAAQABAAAABSq3AAqxAAAAAAABAAUAAAACAAY=";
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);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论