(此问题与我所见过的许多问题相似,但大多数问题对我的工作不够具体)
背景:
我的程序的目的是使使用我的程序的人可以轻松制作自定义的“插件”,然后将其编译并加载到程序中使用(与在我的程序中实现的不完整,缓慢的解析器相比)。我的程序允许用户将代码输入到预定义的类中,从而扩展了与我的程序一起打包的已编译类。他们将代码输入到文本窗格中,然后我的程序将代码复制到被覆盖的方法中。然后,将其保存为(几乎)准备供编译器使用的.java文件。该程序以保存的.java文件作为输入来运行javac(java编译器)。
我的问题是,如何获取它,以便客户端(使用我的编译程序)可以将此java文件(扩展了InterfaceExample)保存在他们的计算机上的任何位置,让我的程序对其进行编译(不说“找不到符号:InterfaceExample” ),然后加载它并调用doSomething()方法?
我一直看到Q&A使用反射或ClassLoader,并且几乎描述了如何编译它,但是对于我来说,没有一个足够详细的描述,我不完全理解它们。
以下内容基于JavaDocs中给出的示例
这会将a
保存File
在testcompile
目录中(基于package
名称要求),然后将其编译File
为Java类。
package inlinecompiler;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class InlineCompiler {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(64);
sb.append("package testcompile;\n");
sb.append("public class HelloWorld implements inlinecompiler.InlineCompiler.DoStuff {\n");
sb.append(" public void doStuff() {\n");
sb.append(" System.out.println(\"Hello world\");\n");
sb.append(" }\n");
sb.append("}\n");
File helloWorldJava = new File("testcompile/HelloWorld.java");
if (helloWorldJava.getParentFile().exists() || helloWorldJava.getParentFile().mkdirs()) {
try {
Writer writer = null;
try {
writer = new FileWriter(helloWorldJava);
writer.write(sb.toString());
writer.flush();
} finally {
try {
writer.close();
} catch (Exception e) {
}
}
/** Compilation Requirements *********************************************************************************************/
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
// This sets up the class path that the compiler will use.
// I've added the .jar file that contains the DoStuff interface within in it...
List<String> optionList = new ArrayList<String>();
optionList.add("-classpath");
optionList.add(System.getProperty("java.class.path") + File.pathSeparator + "dist/InlineCompiler.jar");
Iterable<? extends JavaFileObject> compilationUnit
= fileManager.getJavaFileObjectsFromFiles(Arrays.asList(helloWorldJava));
JavaCompiler.CompilationTask task = compiler.getTask(
null,
fileManager,
diagnostics,
optionList,
null,
compilationUnit);
/********************************************************************************************* Compilation Requirements **/
if (task.call()) {
/** Load and execute *************************************************************************************************/
System.out.println("Yipe");
// Create a new custom class loader, pointing to the directory that contains the compiled
// classes, this should point to the top of the package structure!
URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("./").toURI().toURL()});
// Load the class from the classloader by name....
Class<?> loadedClass = classLoader.loadClass("testcompile.HelloWorld");
// Create a new instance...
Object obj = loadedClass.newInstance();
// Santity check
if (obj instanceof DoStuff) {
// Cast to the DoStuff interface
DoStuff stuffToDo = (DoStuff)obj;
// Run it baby
stuffToDo.doStuff();
}
/************************************************************************************************* Load and execute **/
} else {
for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
System.out.format("Error on line %d in %s%n",
diagnostic.getLineNumber(),
diagnostic.getSource().toUri());
}
}
fileManager.close();
} catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException exp) {
exp.printStackTrace();
}
}
}
public static interface DoStuff {
public void doStuff();
}
}
现在已更新,包括为编译器提供类路径以及已编译类的加载和执行!
问题内容: (此问题与我所见过的许多问题相似,但大多数问题对我的工作不够具体) 背景: 我的程序的目的是使使用我的程序的人可以轻松制作自定义的“插件”,然后将其编译并加载到程序中使用(与在我的程序中实现的不完整,缓慢的解析器相比)。我的程序允许用户将代码输入到预定义的类中,以扩展与我的程序一起打包的已编译类。他们将代码输入到文本窗格中,然后我的程序将代码复制到要重写的方法中。然后,将其保存为(几乎
本文向大家介绍JS加载器如何动态加载外部js文件,包括了JS加载器如何动态加载外部js文件的使用技巧和注意事项,需要的朋友参考一下 今天在网上找到了一个可以动态加载js文件的js加载器,具体代码如下: JsLoader.js JsLoader.js测试 测试结果如下:
现有一个springboot项目,通过扫描二维码查询信息,比如一棵树,扫描二维码后可以看到他相关的信息。但这个项目不止有树类型,还有道路,某个物品。所以将项目分模块开发,核心模块作为一个jar包,复制提供基础服务如数据导入导出。各类型构建成单独的jar。部署时需要那种类型就加载对应的jar。这样做是为了满足不同客户需求。 尝试: java -Xbootclasspath/a:file:./libs
问题内容: 我有这个模块,它将外部库与其他逻辑一起组成组件,而无需将标签直接添加到index.html中: 我注意到ES6规范是静态的,并且在TypeScript编译期间而不是在运行时进行了解析。 无论如何使其可配置,以便从CDN或本地文件夹加载file.js?如何告诉Angular 2动态加载脚本? 问题答案: 如果使用的是system.js,则可以在运行时使用: 如果您使用的是webpack,
问题内容: 我查找了语法并搜索了api,但仍然对该过程感到困惑。我还搜索了Stackoverflow。加载类并从中动态创建对象的正确方法是什么?换句话说,我希望用户指定要创建的对象类型,然后创建该类型的对象。我不需要菜单,因为我希望他们能够选择当前目录中的任何类。 问题答案: 假设该类具有无参数构造函数,则最简单的方法是- 参考-java.lang.Class
问题内容: 我正在编写一个规则引擎,该引擎执行由条件构造确定的简单分配。规则必须为XML格式,这是项目的先决条件。我已经将XML模式建模为类似于简单的代码块。我希望解析XML,然后将其转换为Java代码。然后,我希望在运行时编译(并运行)此代码。这样做意味着我的规则引擎不再充当解释器,而是执行本机Java字节码。 我已经确定了解析阶段,或多或少的Java代码生成阶段。我现在想弄清楚最后一个阶段-运