Java - Dynamic Java code execution (at runtime)

1 - About

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"); 
    }
}

3 - Steps

3.1 - Creating the java source file

  • The class name. The file will have the same name and we will also use it to put it as temporary directory name

final String className = "javademo";

  • Create a temporary directory where the java code and class will be located

Path temp = Paths.get(System.getProperty("java.io.tmpdir"), className);
Files.createDirectories(temp);

  • Creation of the java source file <note tip>You could also extends the SimpleJavaFileObject object as shown in the doc. See SimpleJavaFileObject at javax/tools/JavaCompiler</note>

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());

3.2 - Compiling the source to create a class file

The java compiler library is located at javax/tools/JavaCompiler. It is javax/tools/Tool (bundled in <JDK_HOME>/lib/tools.jar) A tool is a common interface tools that can be invoked from a program.

For Java 10, see Java 10

  • Verification of the presence of the compilation tool archive

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+").");
}

  • The compile part - The real work

// 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();

3.3 - Load and run the class

  • Now that the class was created, we will load it and run it

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


Data Science
Data Analysis
Statistics
Data Science
Linear Algebra Mathematics
Trigonometry

Powered by ComboStrap