package com.redhat.gss.asm;
import java.io.FileOutputStream;
import java.util.Random;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassAdapter;
import static org.objectweb.asm.Opcodes.*;
public class PermGenExploder
{
public static void main(String[] args) throws Exception
{
explode();
}
public static void explode()
{
String name = "a";
MyClassLoader mcl = new MyClassLoader();
ClassWriter cw = new ClassWriter(0);
createClassStructure(cw, name);
byte[] b = cw.toByteArray();
mcl.defineClass(name, b);
// FileOutputStream fos = new FileOutputStream(name + ".class");
// fos.write(b);
// fos.close();
while(true)
{
name = incrementName(name);
ClassReader reader = new ClassReader(b);
cw = new ClassWriter(reader, 0);
ChangeNameAdapter adapter = new ChangeNameAdapter(cw, name);
reader.accept(adapter, 0);
b = cw.toByteArray();
mcl.defineClass(name, b);
// fos = new FileOutputStream(name + ".class");
// fos.write(b);
// fos.close();
}
}
private static void createClassStructure(ClassWriter cw, String name)
{
cw.visit(V1_5, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, name, null, "java/lang/Object", null);
for(int i=0; i<300; i++)
{
cw.visitField(
ACC_PUBLIC + ACC_FINAL + ACC_STATIC,
"STRING"+i,
"Ljava/lang/String;",
null,
getRandomString(300)
).visitEnd();
}
cw.visitEnd();
}
public static String getRandomString(int length)
{
byte[] bb = new byte[length];
Random r = new Random();
for(int i=0; i<length; i++)
{
int k = r.nextInt(94)+32;
if(k == 92) k++; //avoid backslashes
bb[i] = (byte)k;
}
return new String(bb);
}
public static class ChangeNameAdapter extends ClassAdapter
{
private String newName;
public ChangeNameAdapter(ClassVisitor cv, String newName)
{
super(cv);
this.newName = newName;
}
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
cv.visit(version, access, newName, signature, superName, interfaces);
}
}
private static String incrementName(String name)
{
char[] cc = name.toCharArray();
for(int i=cc.length-1; i>=0; i--)
{
char c = cc[i];
if(c == 'z')
{
cc[i] = 'a';
if(i == 0)
{
char[] newcc = new char[cc.length+1];
System.arraycopy(cc, 0, newcc, 1, cc.length);
newcc[0] = 'a';
cc = newcc;
}
}
else
{
cc[i] = ++c;
break;
}
}
return new String(cc);
}
public static class MyClassLoader extends ClassLoader
{
public Class defineClass(String name, byte[] b)
{
return defineClass(name, b, 0, b.length);
}
}
}