首页 文章

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

提问于
浏览
0

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

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

但是,它不起作用 . 获取错误:在com.tom.labs.CompilerTest的java.lang.Class.getMethod(Class.java:1622)中的线程“main”java.lang.NoSuchMethodException:com.tom.labs.Main.test()中出现异常 . 主(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)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()]

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

2 回答

  • 0

    你的“来源”

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

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

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

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

    首先,您应该将包名添加到您的类名 .

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

    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?

相关问题