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从另一个应用程序中编译类文件之后,如何运行它?