【问题标题】:How can we simulate OutOfMemory: Metaspace?我们如何模拟 OutOfMemory: Metaspace?
【发布时间】:2021-09-24 17:21:57
【问题描述】:

我有一个任务是故意模拟 OutOfMemory: Metaspace 错误。我尝试了不同的方法,但没有一个给我需要的结果。有人可以为此分享一个很好的例子吗?

我的第一次尝试(使用 javassist):

static ClassPool classPool = ClassPool.getDefault();

@SneakyThrows
public void task() {

    try {
        for (int i = 0; ; i++) {
            Class cl = classPool.makeClass("task1.Test" + i).toClass();
        }
    } catch (Error er) {
        Runtime.getRuntime().gc();
        log.error(er.getMessage());
    }
}

gradle.properties 文件中的设置:

org.gradle.jvmargs=-XX:MaxMetaspaceSize=70M

但我有一个错误:

异常:java.lang.OutOfMemoryError 从 线程“main”中的 UncaughtExceptionHandler

我没听懂。

我的第二次尝试:

public void task() {
        try {
            URL url = new File("D:/classes").toURI().toURL();
            URL[] urls = {url};

            ClassLoadingMXBean loadingMXBean = ManagementFactory.getClassLoadingMXBean();

            List<ClassLoader> classLoaders = new ArrayList<>();

            while (true) {
                ClassLoader classLoader = new URLClassLoader(urls);
                classLoaders.add(classLoader);
                classLoader.loadClass("test1.Test1");

                log.info("Total: " + loadingMXBean.getTotalLoadedClassCount());
                log.info("Active: " + loadingMXBean.getLoadedClassCount());
                log.info("Unloaded: " + loadingMXBean.getUnloadedClassCount());
            }
        } catch (Exception ex) {
            log.error(ex + ex.getMessage());
        }
    }

但它不起作用,IDEA 通知我有法律记忆。

【问题讨论】:

  • 你真的能听懂吗? JVM 会为你打印出来,无需捕获和记录。 (也尝试在该状态下做一些事情可能会产生更多错误)
  • 我想我刚刚找到了您想要的示例(错误 #4):geeksforgeeks.org/understanding-outofmemoryerror-exception-java
  • 它仍然得到同样的错误。如果我应该编写测试来检查所需的异常怎么办,即要求获得 OutOfMemoryError: Metaspace?我能以某种方式抓住它并从中获取信息吗?
  • 我有一个任务由谁分配,目的是什么?

标签: java memory out-of-memory


【解决方案1】:

您忘记了类加载在 JVM 中是如何工作的。类加载器将首先尝试让其父类加载您正在寻找的类。为了使您的测试正常工作,您需要一个自定义类加载器,它不会为您正在测试的那个类委托给它的父类。

这是一个适用于 Java 8 的示例

DummyClass.java(默认包)

public class DummyClass {
  static String padding = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
}

Test.java(默认包)

import java.lang.management.ClassLoadingMXBean;
import java.lang.management.ManagementFactory;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

public class Test {
    
    public static void main(String[] args) {

        try {
            
            URL url = Test.class.getResource("").toURI().toURL();
            System.out.println("URL = " + url);
            URL[] urls = {url};
    
            ClassLoadingMXBean loadingMXBean = ManagementFactory.getClassLoadingMXBean();
    
            List<ClassLoader> classLoaders = new ArrayList<>();

            System.out.println("Total: " + loadingMXBean.getTotalLoadedClassCount());
            System.out.println("Active: " + loadingMXBean.getLoadedClassCount());
            System.out.println("Unloaded: " + loadingMXBean.getUnloadedClassCount());

            int i = 0;
            while ( true ) {
                i++;
                System.out.println("### Iteration " + i + " ###");
                ClassLoader classLoader = new URLClassLoader(urls) {
                    @Override
                    public Class<?> loadClass(String name) throws ClassNotFoundException {
                        final Class<?> loadedClass;
                        if ( "DummyClass".equals(name) ) {
                            System.out.println (this + " - finding class " + name);
                            loadedClass = findClass(name);
                            System.out.println (this + " - loading class " + loadedClass);
                        } else {
                            // delegate to parent
                            loadedClass = this.getParent().loadClass(name);
                        }
                        return loadedClass;
                    }
                };
                
                classLoaders.add(classLoader);
                classLoader.loadClass("DummyClass");
    
                System.out.println("Total: " + loadingMXBean.getTotalLoadedClassCount());
                System.out.println("Active: " + loadingMXBean.getLoadedClassCount());
                System.out.println("Unloaded: " + loadingMXBean.getUnloadedClassCount());
            }
        } catch ( Exception ex ) {
            ex.printStackTrace();
        }
        
    }
}

使用-XX:MaxMetaspaceSize=100m 运行,我最终得到了这个:

> ### Iteration 16318 ### 
> Test$1@531ed68e - finding class DummyClass
> Test$1@531ed68e - loading class class DummyClass
> Total: 16747 Active:
> 16747 Unloaded: 0
> ### Iteration 16319 ### 
> Test$1@6bbd4048 - finding class DummyClass 
> Exception in thread "main" java.lang.OutOfMemoryError: Metaspace  at
> java.lang.ClassLoader.defineClass1(Native Method)     at
> java.lang.ClassLoader.defineClass(ClassLoader.java:756)   at
> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
>   at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)     at
> java.net.URLClassLoader.access$100(URLClassLoader.java:74)    at
> java.net.URLClassLoader$1.run(URLClassLoader.java:369)    at
> java.net.URLClassLoader$1.run(URLClassLoader.java:363)    at
> java.security.AccessController.doPrivileged(Native Method)    at
> java.net.URLClassLoader.findClass(URLClassLoader.java:362)    at
> Test$1.loadClass(Test.java:42)    at Test.main(Test.java:53)

【讨论】:

    猜你喜欢
    • 2011-02-16
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 2021-07-02
    • 1970-01-01
    • 2023-01-03
    相关资源
    最近更新 更多