package com.company;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
/**
* This program will generate 1000 classes.
* It's "useful" to test the limit of the Metaspace using -XX:MaxMetaspaceSize.
*
* Start program with :
* java -Djava.home="C:\Program Files\Java\jdk1.8.0_60\jre" -XX:MaxMetaspaceSize=10m -classpath "C:\wip\test\out\production\test" com.company.TestMetaspaceLimit
*
* - java.home : by default, it's without \jre, and `ToolProvider.getSystemJavaCompiler()` returns null.
* - the classpath should be the same as the CLASS_OUTPUT location given in the program (where the .class are).
*
* With 10m of metaspace, it crashes at HelloWorld 304. :-)
*/
public class TestMetaspaceLimit {
public static void main(String... args) throws Exception {
for (int i = 0; i < 1000; i++) {
createClass(i);
}
}
public static void createClass(int i) throws Exception {
File sourceFile = new File("Hello" + i + ".java");
FileWriter writer = new FileWriter(sourceFile);
writer.write("public class Hello" + i + " { public void talk() { System.out.println(\"Hello world " + i + "\"); } }");
writer.close();
// Compile the file
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singletonList(new File("C:\\wip\\test\\out\\production\\test")));
compiler.getTask(null, fileManager, null, null, null, fileManager.getJavaFileObjectsFromFiles(Collections.singletonList(sourceFile))).call();
fileManager.close();
// delete the source file
sourceFile.deleteOnExit();
makeItTalk(i);
}
public static void makeItTalk(int i) throws Exception {
Class<?> klass = Class.forName("Hello" + i);
Method thisMethod = klass.getDeclaredMethod("talk");
thisMethod.invoke(klass.newInstance());
}
}