0
votes

I got the following code which copy from a tutorial:

package com.tom.labs;

import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class CompilerTest {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        String source = "public class Main { " +
                " public static void main(String[] args) {" +
                "   System.out.println(\"Hello World!\");" +
                " }" +
                " public static void test() { " +
                " System.out.println(\"Hello World!\");" +
                " } " +
                "}";
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        StringSourceJavaObject sourceObject = new CompilerTest.StringSourceJavaObject("Main", source);
        Iterable fileObjects = Arrays.asList(sourceObject);
        CompilationTask task = compiler.getTask(null, fileManager, null, null, null, fileObjects);
        boolean result = task.call();
        if (result) {
            ClassLoader loader = CompilerTest.class.getClassLoader();
            Class<?> clazz = loader.loadClass("com.tom.labs.Main");
            Method method = clazz.getMethod("test", new Class<?>[] {});
            method.invoke(null, new Object[] {});
        }
    }

    static class StringSourceJavaObject extends SimpleJavaFileObject {
        private String content = null;
        public StringSourceJavaObject(String name, String content) throws URISyntaxException {
            super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.content = content;
        }
        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
            return content;
        }
    }
}

However,it doesn't work. Getting error: Exception in thread "main" java.lang.NoSuchMethodException: com.tom.labs.Main.test() at java.lang.Class.getMethod(Class.java:1622) at com.tom.labs.CompilerTest.main(CompilerTest.java:38)

Can anybody help me out? Updte:

I printed out the output of getMethods: [public static void com.tom.labs.Main.main(java.lang.String[]), public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]

It's very strange, method test is not in there.

2
there is no class called "Main" and as no class is there, there is no method called "test".Alpesh Prajapati
@AlpeshPrajapati I don't think so,if no class,the exception should be: java.lang.ClassNotFoundException:Tom
have you declared method "test()" ?Alpesh Prajapati
Did you try it without the 2nd parameter to getMethod() and invoke()? (I don't think you need to specify them at all if they are empty.)Turix
@Turix Still the same exception.Tom

2 Answers

1
votes

Your 'source'

String source = "public class Main { " +
                " public static void main(String[] args) {" +
                "   System.out.println(\"Hello World!\");" +
                " }" +
                " public static void test() { " +
                " System.out.println(\"Hello World!\");" +
                " } " +
                "}";

has no namespace. Either you should add a package keyword to it, or change

Class<?> clazz = loader.loadClass("com.tom.labs.Main");

to

Class<?> clazz = loader.loadClass("Main");
0
votes

First you should add package name to your class name.

Besides package name, please check weather the generated class as put in your class path. This could be done by adding class output folder option when invoking compilation task:

CompilationTask task = compiler.getTask(null, fileManager, null, Arrays.asList("-d", ""), null, fileObjects);

There is a fantastic but light weight library could do your work in just one call, and compile source and load class totally in memory, please have a visit:

After using JavaCompiler to compiler class files from within another application, how do I then run it?