动态编译java源代码和反射调用问题

时间:2012-06-29 07:05:04

标签: java

我从教程中获得了以下代码:

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

然而,它不起作用。得到错误: 线程“main”中的异常java.lang.NoSuchMethodException:com.tom.labs.Main.test()     at java.lang.Class.getMethod(Class.java:1622)     在com.tom.labs.CompilerTest.main(CompilerTest.java:38)

有人可以帮帮我吗? Updte:

我打印出了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)抛出java.lang.InterruptedException,public final void java.lang.Object.wait()抛出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()]

这很奇怪,方法测试不在那里。

2 个答案:

答案 0 :(得分:1)

你的'来源'

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

没有命名空间。您应该向其添加package关键字,或者更改

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

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

答案 1 :(得分:0)

首先,您应该将包名添加到您的班级名称。

除了包名,请查看天气生成的课程,如同课程路径一样。这可以通过在调用编译任务时添加类输出文件夹选项来完成:

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

有一个很棒但很轻的库可以在一次调用中完成你的工作,并且完全在内存中编译源码和加载类,请访问:

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