Java程序要故意填充PermGen?

2024-04-13

当 PermGen 已满时,Glassfish 有时无法停止,在这种情况下asadmin stop-domain domain1不起作用。在 Glassfish 2.1.1 中,它会永远坐在那里;在 3.x 之后超时AS_ADMIN_READTIMEOUT。所以我现在正在编写 Glassfish 停止脚本,该脚本将在一定的超时后杀死/杀死 -9 它以确保它停止。

为了充分测试这一点,我需要重现这个 PermGen 完整场景。怎样才能故意填满PermGen呢?我目前正在使用 Java 1.7.0_45(如果有的话)。我已经编写了一个程序来填充堆,但这对我来说是一个新程序,我想我会转向SO。它需要是我可以部署到 GF 中的东西(.war?),这可能会更棘手(不确定)。感谢任何帮助,非常感谢。


我有东西给你。我不知道如何在这里上传 jar 文件,所以只是在这里添加文件。

方法:ClassGenerator 类在 while 循环中创建一个新的类加载器,并一遍又一遍地加载同一个类,直到用完 permgen。现在您会注意到有一个列表保存了已加载类的引用。这是为了防止 JVM 卸载这些类:)。

文件解释
第一张图显示,当您运行该程序时,它耗尽了永久代空间。如果您想在 Eclipse 中进行设置,第二张图显示了项目的结构。我在 eclipse 中测试了它,并将其导出为可运行的 jar 文件,它在两种情况下都有效。

Run as a runnable jar file and it ran out of permgen. Program ran out of permgen

Eclipse 项目设置

类生成器类

package com.vkg;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class ClassGenerator {
    private static final int BUFFER = 1024;
    private List<Class<?>> classList = new ArrayList<Class<?>>();

    public static void main(String[] args) {
        ClassGenerator classGenerator = new ClassGenerator();
        // Load just some class with class loaders until perm gen space fills.
        while (true) {
            classGenerator.classLoader();
        }
    }

    private void classLoader() {
        ClassLoader classLoader = new ClassLoader() {
            public Class<?> loadClass(String classNameWithPackage)
                    throws ClassNotFoundException {
                if (!classNameWithPackage.contains("DummyClass")) {
                    return super.loadClass(classNameWithPackage);
                }
                String className = classNameWithPackage.replace('.', '/')
                        + ".class";
                byte[] classData = null;
                InputStream inputStream = null;
                try {
                    inputStream = getResourceAsStream(className);
                    byte[] buffer = new byte[BUFFER];
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    int bytesRead = -1;
                    while ((bytesRead = inputStream.read(buffer, 0, BUFFER)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    classData = outputStream.toByteArray();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (inputStream != null) {
                        try {
                            inputStream.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                Class<?> c = defineClass(classNameWithPackage, classData, 0,
                        classData.length);
                resolveClass(c);
                System.out
                        .println("Steve I am loading another copy of Dummy class. Soon Permgen will fill.");
                classList.add(c);
                return c;
            }
        };

        try {
            Class.forName("com.vkg.DummyClass", true, classLoader);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

虚拟类。这可以是任何类。该类的唯一目的是多次加载。没有其他用途。此类中不执行任何逻辑。主要逻辑在ClassGenerator.java中

package com.vkg;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class DummyClass {
    public void classLoader() {
        ClassLoader classLoader = new ClassLoader() {
            public Class<?> loadClass(String classNameWithPackage) throws ClassNotFoundException {
                 if(!classNameWithPackage.contains("DummyClass")) {
                     return  super.loadClass(classNameWithPackage);
                 } 
                 String className = classNameWithPackage.replace('.', '/') + ".class";
                byte[] classData = null;
                try {
                    InputStream inputStream = getResourceAsStream(className);
                    byte[] buffer = new byte[1];
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    int bytesRead = -1;
                    while ((bytesRead = inputStream.read(buffer, 0, 1)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    classData = outputStream.toByteArray();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }

                Class<?> c = defineClass(classNameWithPackage, classData, 0, classData.length);
                resolveClass(c);
                System.out.println("Steve I am loading another copy of Dummy class. Soon Permgen will fill.");
                return c;
            }
        };

        try {
            Class.forName("com.vkg.DummyClass", true, classLoader);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

希望它可以帮助您测试服务器崩溃。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java程序要故意填充PermGen? 的相关文章

随机推荐