import javax.tools.*; // Compilation
File helloWorldJava = new File ("HelloWorld.java"); // source file
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler ();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject> ();
StandardJavaFileManager fileManager = compiler.getStandardFileManager (diagnostics, null, null);
ArrayList<String> optionList = new ArrayList<String> ();
// optionList.add("-classpath");
// optionList.add("directory");
Iterable<? extends JavaFileObject> compilationUnit =
fileManager.getJavaFileObjectsFromFiles (Arrays.asList (helloWorldJava));
JavaCompiler.CompilationTask task = compiler.getTask (
null,
fileManager,
diagnostics,
optionList,
null,
compilationUnit);
if (task.call ())
{
/* ... */
}
URLClassLoader classLoader =
new URLClassLoader (new URL[] { new File ("./").toURI ().toURL () });
Class loadedClass = classLoader.loadClass ("testcompile.HelloWorld");
Object obj = loadedClass.newInstance ();
try
{
Method m = loadedClass.getMethod ("doStuff");
m.invoke (obj);
}
catch (NoSuchMethodException ex) { }
catch (SecurityException ex) { }
catch (IllegalArgumentException ex) { }
catch (InvocationTargetException ex) { }
/*https://stackoverflow.com/questions/21544446/how-do-you-dynamically-compile-and-load-external-java-classes */
private void compile ()
{
/*
StringBuilder sb = new StringBuilder (64);
sb.append ("package testcompile;\n");
sb.append ("public class HelloWorld {\n");
sb.append (" public void doStuff() {\n");
sb.append (" System.out.println(\"Hello world\");\n");
sb.append (" }\n");
sb.append ("}\n");
*/
String source = editor.getText ();
File helloWorldJava = new File ("testcompile/HelloWorld.java");
if (helloWorldJava.getParentFile ().exists () || helloWorldJava.getParentFile ().mkdirs ())
{
try
{
Writer writer = null;
try
{
writer = new FileWriter (helloWorldJava);
// writer.write (sb.toString ());
writer.write (source);
writer.flush ();
}
finally
{
try
{
writer.close ();
}
catch (Exception e)
{
}
}
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject> ();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler ();
StandardJavaFileManager fileManager = compiler.getStandardFileManager (diagnostics, null, null);
// This sets up the class path that the compiler will use.
// I've added the .jar file that contains the DoStuff interface within in it...
ArrayList<String> optionList = new ArrayList<String> ();
// optionList.add("-classpath");
// optionList.add(System.getProperty("java.class.path") + File.pathSeparator + "dist/InlineCompiler.jar");
Iterable<? extends JavaFileObject> compilationUnit =
fileManager.getJavaFileObjectsFromFiles (Arrays.asList (helloWorldJava));
JavaCompiler.CompilationTask task = compiler.getTask (
null,
fileManager,
diagnostics,
optionList,
null,
compilationUnit);
if (task.call ())
{
// Create a new custom class loader, pointing to the directory that contains the compiled
// classes, this should point to the top of the package structure!
URLClassLoader classLoader = new URLClassLoader (new URL[]
{
new File ("./").toURI ().toURL ()
});
// Load the class from the classloader by name....
Class loadedClass = classLoader.loadClass ("testcompile.HelloWorld");
Object obj = loadedClass.newInstance ();
try
{
Method m = loadedClass.getMethod ("doStuff");
m.invoke (obj);
}
catch (NoSuchMethodException ex) { }
catch (SecurityException ex) { }
catch (IllegalArgumentException ex) { }
catch (InvocationTargetException ex) { }
}
else
{
for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics ())
{
System.out.format ("Error on line %d in %s%n",
diagnostic.getLineNumber (),
diagnostic.getSource ().toUri ());
}
}
fileManager.close ();
} catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException exp)
{
exp.printStackTrace ();
}
}
}