Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I programmatically compile and instantiate a Java class?

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?

like image 563
unj2 Avatar asked May 31 '10 22:05

unj2


People also ask

How do you compile and run a Java class?

Type 'javac MyFirstJavaProgram. java' and press enter to compile your code. If there are no errors in your code, the command prompt will take you to the next line (Assumption: The path variable is set). Now, type ' java MyFirstJavaProgram ' to run your program.

Which command is used to compile the Java program?

The javac command reads source files that contain module, package and type declarations written in the Java programming language, and compiles them into class files that run on the Java Virtual Machine.


1 Answers

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 = new File("/java"); // On Windows running on C:\, this is C:\java. 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.newInstance(); // Should print "world". System.out.println(instance); // Should print "test.Test@hashcode". 

Which yields like

hello world test.Test@ab853b 

Further use would be more easy if those classes implements a certain interface which is already in the classpath.

SomeInterface instance = (SomeInterface) cls.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")); 
like image 72
BalusC Avatar answered Sep 21 '22 08:09

BalusC