1

I have a java source code which would be compiled at runtime. I'm compiling the source code (present as a string) and loading it to a class as below :

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("TakeAdvantageOftMapComponents", true, classLoader);

This class contains a method which I need to call named runJob. Normally I'd do it like:

TakeAdvantageOftMapComponents c  = new TakeAdvantageOftMapComponents();
c.runJob(new string[]);

Now this same method is present in the class which I compile at runtime. But how do I call it ?

Aneesh
  • 1,651
  • 2
  • 20
  • 33
  • I figured it out using Relection - based on an answer given here :I figured it out using Relection - based on an answer given [here][1] http://stackoverflow.com/questions/160970/how-do-i-invoke-a-java-method-when-given-the-method-name-as-a-string – Aneesh Jun 26 '14 at 04:26

1 Answers1

1

Better than using reflection to call the method you want, you might want to declare an interface that your class would extend, such as:

package ccjmne;

public interface JobRunner {

    public void runJob(final String[] args);
}

... and make your class implement that interface:

File: /home/eric/stackoverflow/A.java

package stackoverflow;

public class A implements ccjmne.JobRunner {
    public void runJob(final String args[]) {
        for(final String str : args) {
            System.out.println(str);
        }
    }
}

And finally, load that class as follows:

final Class<JobRunner> cls = (Class<JobRunner>) Class.forName("stackoverflow.A", true, classLoader);

Note that I know that I've a JobRunner here.

Thus, I can simply do:

cls.newInstance().runJob("Hello world!".split(" "));

... And you're done!


Sample working code:

package ccjmne;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

public class JobRunnerTest {

    public static void main(final String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, MalformedURLException {
        final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        final File root = new File("/home/eric/");
        compiler.run(null, null, null, root + "/stackoverflow/A.java");
        final URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
        final Class<JobRunner> cls = (Class<JobRunner>) Class.forName("stackoverflow.A", true, classLoader);
        cls.newInstance().runJob("Hello world!".split(" "));
    }
}

Output:

Hello
world!
ccjmne
  • 7,914
  • 3
  • 41
  • 56
  • This would have worked - but I have no control over the source. It's being generated by an external program. But up-voting for the detailed answer. – Aneesh Jun 26 '14 at 07:36