Java程序故意填满PermGen? [英] Java program to deliberately fill up PermGen?

查看:127
本文介绍了Java程序故意填满PermGen?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

解决方案

我有一些事情可以帮助你。我不知道如何在这里上传一个jar文件,所以在这里添加文件。


$ b 方法: ClassGenerator类创建一个新的类加载器一个while循环并一次又一次地加载相同的类,直到它耗尽了permgen。现在你会注意到有一个列表保存了加载类的引用。这是为了防止JVM卸载这些类:)。



文件解释

第一张图像显示当你运行它的程序将耗尽permgen空间。第二张图片显示了如果你想在eclipse中设置项目的结构。我在eclipse中测试它,并将它作为可运行的jar文件导出,它在两种情况下都能正常工作。


作为可运行的jar文件运行,并且运行超时。 >



Eclipse项目设置





ClassGenerator类

  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;
私人清单< Class<?>> classList = new ArrayList< Class<>>();

public static void main(String [] args){
ClassGenerator classGenerator = new ClassGenerator();
//使用类加载器加载一些类,直到perm gen空间填充。
while(true){
classGenerator.classLoader();



private void classLoader(){
ClassLoader classLoader = new ClassLoader(){
public Class<?> loadClass(String classNameWithPackage)
抛出ClassNotFoundException {
if(!classNameWithPackage.contains(DummyClass)){
return super.loadClass(classNameWithPackage);
}
String className = classNameWithPackage.replace('。','/')
+.class;
byte [] classData = null;
InputStream inputStream = null;
尝试{
inputStream = getResourceAsStream(className);
byte [] buffer = new byte [BUFFER];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int bytesRead = -1; ((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我正在加载Dummy类的另一个副本,很快Permgen会填充。);
classList.add(c);
return c;
}
};

尝试{
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;
尝试{
InputStream inputStream = getResourceAsStream(className);
byte [] buffer = new byte [1];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int bytesRead = -1; ((bytesRead = inputStream.read(buffer,0,1))!= -1){
outputStream.write(buffer,0,bytesRead);
while
}
classData = outputStream.toByteArray();
}
catch(IOException e){
e.printStackTrace();
}

Class<?> c = defineClass(classNameWithPackage,classData,0,classData.length);
resolveClass(c);
System.out.println(Steve我正在加载Dummy类的另一个副本,很快Permgen会填充。);
return c;
}
};

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

希望它能帮助你测试你的服务器崩溃。

Glassfish sometimes fails to stop when the PermGen is full, in this case asadmin stop-domain domain1 doesn't work. In Glassfish 2.1.1 it would just sit there forever; in 3.x it times out after AS_ADMIN_READTIMEOUT. So I am now working on my Glassfish stop script that will kill/kill -9 it after a certain timeout to guarantee it gets stopped.

To fully test this I need to reproduce this PermGen full scenario. How can I deliberately fill up PermGen? I'm currently using Java 1.7.0_45 if that matters. I've written a program to fill up heap but this is a new one for me, I figured I'd turn to SO. It might be trickier (not sure) that it needs to be something (a .war?) I can deploy into GF. Any help is appreciated, thanks so much.

解决方案

I have some thing for you. I don't know how to upload a jar file here so just adding files here.

Approach: ClassGenerator class creates a new class loader in a while loop and loads the same class over and over again until it run out of permgen. Now you will notice there is a list that keeps a reference of the loaded class. That is to prevent JVM from unloading those classes :).

Files Explained
The first image shows that when you run the program it run out of permgen space. Second image shows the structure of the project if you want to set it up in eclipse. I tested it within eclipse and exported it as a runnable jar file it works in both cases.

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

Eclipse Project setup

ClassGenerator class

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();
        }
    }
}

Dummy class. This can be any class. Sole purpose of this class is to get loaded large number of times. No other use. No logic gets executed from this class. Main logic is in 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();
        }
    }
}

Hope it helps you test your server crash.

这篇关于Java程序故意填满PermGen?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆