How to create, compile and run Java code at runtime making it a dynamic, scripting language.
The below section is showing parts of the whole script highlighting all the steps needed to create and run dynamic java code.
You can find the whole script at DynamicRuntimeExecutionTest.java
The sample dynamic code is a simple class with a static method that prints Hello Nico
public class java demo {
public static void run() {
System.out.println("Hello Nico");
}
}
final String className = "javademo";
Path temp = Paths.get(System.getProperty("java.io.tmpdir"), className);
Files.createDirectories(temp);
Path javaSourceFile = Paths.get(temp.normalize().toAbsolutePath().toString(), className + ".java");
System.out.println("The java source file is loacted at "+javaSourceFile);
String code = "public class " + className + " {" +
"public static void run() {\n" +
" System.out.println(\"Hello Nico\"); \n" +
" }" +
"}";
Files.write(javaSourceFile, code.getBytes());
The java compiler library is located at javase/9/docs/api/javax/tools/JavaCompiler.html. It is javase/9/docs/api/javax/tools/Tool.html (bundled in
/lib/tools.jar'') A tool is a common interface tools that can be invoked from a program.For Java 10, see Java 10
final String toolsJarFileName = "tools.jar";
final String javaHome = System.getProperty("java.home");
Path toolsJarFilePath = Paths.get(javaHome, "lib", toolsJarFileName);
if (!Files.exists(toolsJarFilePath)){
System.out.println("The tools jar file ("+toolsJarFileName+") could not be found at ("+toolsJarFilePath+").");
}
// Definition of the files to compile
File[] files1 = {javaSourceFile.toFile()};
// Get the compiler
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// Get the file system manager of the compiler
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
// Create a compilation unit (files)
Iterable<? extends JavaFileObject> compilationUnits =
fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files1));
// A feedback object (diagnostic) to get errors
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
// Compilation unit can be created and called only once
JavaCompiler.CompilationTask task = compiler.getTask(
null,
fileManager,
diagnostics,
null,
null,
compilationUnits
);
// The compile task is called
task.call();
// Printing of any compile problems
for (Diagnostic diagnostic : diagnostics.getDiagnostics())
System.out.format("Error on line %d in %s%n",
diagnostic.getLineNumber(),
diagnostic.getSource());
// Close the compile resources
fileManager.close();
ClassLoader classLoader = DynamicRuntimeExecutionTest.class.getClassLoader();
URLClassLoader urlClassLoader = new URLClassLoader(
new URL[] { temp.toUri().toURL() },
classLoader);
Class javaDemoClass = urlClassLoader.loadClass(className);
Method method = javaDemoClass.getMethod("run");
method.invoke(null); // null because this is a static method
Result:
Hello Nico