问题
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.
回答1:
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.
来源:https://stackoverflow.com/questions/23415288/java-program-to-deliberately-fill-up-permgen