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

Dynamic compile java source code and reflection invoke issue

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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()中出现异常在Java.Lang.Class .GETMeod(class .java:1622)在COM.Tom .Labs。CopySertEng.Mulk(CimuleTest.java:38)

有人能帮我吗?Updte:

我打印出getmethods的输出:[公共静态虚空COM.Tom .Maul.Mava.主(java. Lang.Stult[]),公共最终空隙java. Lang.Object。抛出JavaLang.DistelExtExpCuint,公共最终原生java. Lang.Object。等待(long)抛出java. Lang.DisteleExpCuint,公共最终空隙Java.Lang.Objist.WaIT()抛出JavaLang.Debug TestExpPress,公共布尔JavaLAN。G.Objor。(Java.Lang.Object),public java. Lang.StaskJava.Lang.Objist.toStrug(),公共原生int java. Lang.Objas.HasCODE(),公共最终原生java. Lang.java对象.Lang.Objult.GeCype(),公共最终原生java.Lang.Objist.NoTIFY(),公共最终原生Java.Lang.Obj.

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


你的"源头"

1
2
3
4
5
6
7
8
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关键字,或者更改

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

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


首先,您应该将包名称添加到类名中。

除了包名之外,请检查生成的类是否符合类路径。这可以通过在调用编译任务时添加类输出文件夹选项来实现:

compilationtask task=compiler.gettask(空,filemanager,空,array.aslist("-d","),空,fileobjects);

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

在使用javacompiler从另一个应用程序中编译类文件之后,如何运行它?