【发布时间】:2013-03-31 13:53:23
【问题描述】:
我知道这个问题已经被问了很多,但我仍然没有一个好的解决方案,我仍然不明白某些部分。所以我需要以编程方式编译 *.java 文件。
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
是我正在使用的,并且(正如预期的那样)编译器是null。
现在,我确实知道我必须使用 JDK 而不是 JRE 作为“运行时”,但这里有一些我不明白的地方:仅仅将 tools.jar 放在应用程序的类路径中还不够吗?那么可以访问 Java Compiler API 吗?如果这是真的,那么独立的 Java 应用程序和基于 Web 的应用程序之间是否存在(我认为存在)差异。
实际上,我正在尝试从 PlayFramework webapp 调用 JavaCompiler,所以我发现,也许这个解决方案(包括 tools.jar)仅适用于独立应用程序?
我还尝试创建一个自定义 ClassLoader 并使用反射调用上述方法,但我得到的只是 null 用于 compiler 对象:
ClassLoader classloader = app.classloader();
File file = new File("lib/tools.jar");
URL url = file.toURI().toURL();
URL[] urls = new URL[]{url};
ClassLoader newCL = new URLClassLoader(urls, classloader) {
};
Class<?> loadClass = newCL.loadClass("javax.tools.ToolProvider");
Method method = loadClass.getMethod("getSystemJavaCompiler", null);
Object object = method.invoke(null);
System.out.println("Object: " + object); // NULL
上面代码的解释:
- 为了简单起见,我没有包含 try/catch。
- app.classloader() 是一个 Play-method,它返回 App 的 ClassLoader
-
tools.jar包含在 Play 项目的我的 lib 文件夹中(这意味着它位于项目的类路径中 - 根据 Play 文档)
我很确定在 Play 能够加载 Java Compiler 类之前我还需要做一些其他事情,我只是不知道我缺少什么。
Runtime.exec("javac myFile.java") 和 Eclipse JDT 编译器之类的选项我都知道,但这不是我想要的。
哦,像 System.setProperty("java.home", "PATH_TO_YOUR_JDK"); 和 ToolProvider.getSystemJavaCompiler(); 这样的东西正在工作,但我觉得这个解决方案太丑了。
最好的问候
编辑:(提供附加信息并反映最后状态) 这是 web-app-structure 的基本表示:
myApp
|-conf\...
|-lib\MyJar.jar
|-lib\tools.jar
|-logs\...
|-...
MyJar.jar 现在有一个 META-INF/MANIFEST.MF 文件,其内容如下:
Manifest-Version: 1.0
Sealed: true
Main-Class: here.comes.my.main.class
Class-Path: tools.jar
没有启动 Play 应用程序,我正在尝试(在 lib 文件夹中):java -jar MyJar.jar - 我的简单 main 方法尝试调用编译器 (ToolProvider.getSystemJavaCompiler();) 并返回null。所以这让我相信,这个问题与 Play 无关——在正常运行我的 Jar 时,我什至无法获得编译器!
【问题讨论】:
标签: java compiler-construction playframework playframework-2.0 tools.jar