How do I programmatically compile and instantiate a Java class?
dynamic-loading, java, reflection
Solution
How do I load a Java Class that is not compiled?
You need to compile it first. This can be done programmatically with the `javax.tools` API. This only requires the JDK being installed at the local machine on top of JRE.
Here's a basic kickoff example (leaving obvious exception handling aside):
// Prepare source somehow.
String source = "package test; public class Test { static { System.out.println(\"hello\"); } public Test() { System.out.println(\"world\"); } }";
// Save source in .java file.
File root = Files.createTempDirectory("java").toFile();
File sourceFile = new File(root, "test/Test.java");
sourceFile.getParentFile().mkdirs();
Files.write(sourceFile.toPath(), source.getBytes(StandardCharsets.UTF_8));
// Compile source file.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, sourceFile.getPath());
// Load and instantiate compiled class.
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
Class<?> cls = Class.forName("test.Test", true, classLoader); // Should print "hello".
Object instance = cls.getDeclaredConstructor().newInstance(); // Should print "world".
System.out.println(instance); // Should print "test.Test@hashcode".
Which yields like
hello
world
test.Test@cafebabe
Further use would be more easy if those classes `implements` a certain interface which is already in the classpath.
SomeInterface instance = (SomeInterface) cls.getDeclaredConstructor().newInstance();
Otherwise you need to involve the Reflection API to access and invoke the (unknown) methods/fields.
That said and unrelated to the actual problem:
properties.load(new FileInputStream(new File("ClassName.properties")));
Letting `java.io.File` rely on current working directory is recipe for portability trouble. Don't do that. Put that file in classpath and use `ClassLoader#getResourceAsStream()` with a classpath-relative path.
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("ClassName.properties"));
Problem
I have the class name stored in a property file. I know that the classes store will implement IDynamicLoad. How do I instantiate the class dynamically? Right now I have ``` Properties foo = new Properties(); foo.load(new FileInputStream(new File("ClassName.properties"))); String class_name = foo.getProperty("class","DefaultClass"); //IDynamicLoad newClass = Class.forName(class_name).newInstance(); ``` Does the newInstance only load compiled .class files? How do I load a Java Class that is not compiled?