Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
以编程方式编译java文件_Java_Compiler Construction_Playframework_Playframework 2.0_Tools.jar - Fatal编程技术网

以编程方式编译java文件

以编程方式编译java文件,java,compiler-construction,playframework,playframework-2.0,tools.jar,Java,Compiler Construction,Playframework,Playframework 2.0,Tools.jar,我知道这已经被问了很多问题,也回答了很多问题,但是我仍然没有一个好的解决方案,我仍然不理解其中的一些部分。因此,我需要以编程方式编译*.java文件 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 是我正在使用的,并且(正如预期的那样)编译器为null。 现在,我知道我必须使用JDK而不是JRE作为“运行时”,但有一点我不明白:仅仅将tools.jar放在应用程序的类路径中,然后访问Java编译器API,这还不够吗?如

我知道这已经被问了很多问题,也回答了很多问题,但是我仍然没有一个好的解决方案,我仍然不理解其中的一些部分。因此,我需要以编程方式编译*.java文件

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
是我正在使用的,并且(正如预期的那样)编译器为
null
。 现在,我知道我必须使用JDK而不是JRE作为“运行时”,但有一点我不明白:仅仅将
tools.jar
放在应用程序的类路径中,然后访问Java编译器API,这还不够吗?如果这是真的,那么独立java应用程序和基于web的应用程序之间是否存在(我认为存在)区别。 实际上,我正试图从PlayFramework Web应用程序中调用Java编译器,所以我想,也许这个解决方案(包括
tools.jar
)只适用于独立应用程序

我还尝试创建一个自定义类加载器并通过反射调用上述方法,但我得到的是
编译器
对象的
null

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
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
。因此,这让我相信,这个问题与游戏无关——在正常运行Jar时,我甚至无法获得编译器

文件中说,要运行Play框架,您需要JDK 6或更高版本。
您是如何使用jre运行它的

无论如何,如果
getSystemJavaCompiler
返回null,则表示类路径中没有
tools.jar
,或者它已损坏。如果是Sun/OracleJava,请确保其中包含
com.Sun.tools.javac.api.JavacTool

如果您想使用自定义类加载器,则需要加载的是JavacTool类,而不是ToolProvider。看看java 6中的实现方式:

        URL[] urls = {file.toURI().toURL()};
        ClassLoader cl = URLClassLoader.newInstance(urls);
        cl.setPackageAssertionStatus("com.sun.tools.javac", true);
        return Class.forName(defaultJavaCompilerName, false, cl);
其中
defaultJavaCompilerName=“com.sun.tools.javac.api.JavacTool”


将其子类化为
JavaCompiler
并获取新实例-您将拥有您的编译器。

web应用程序和独立应用程序之间没有区别

您不应该将tools.jar打包到webapp类路径中。Java中的类加载器通常只能自下而上工作。因此,作为jdk一部分的ToolProvider不会在webapp类路径中看到您的tools.jar(它不能向下查看webapp类路径)


解决方案:使用JDK并确保指向它,或者将tools.jar放在JavaExtDir中。您可以通过将属性-Djava.ext.dir设置为您喜欢的任何目录来覆盖ext dir。

JAVA\u HOME
在我的开发机器上设置,在请求时返回JDK的路径。但是从运行Play应用程序中获取
“java.home”
属性(使用
System.getProperty(…)
)会返回JRE的路径。所以这可能是唯一的问题。但是当我的类路径中有
tools.jar
时,应该不会有问题。我非常确定
tools.jar
在我的类路径中(在web应用程序运行期间检查了它),并且文件没有损坏。我将尝试上面提到的类加载功能。我在ubuntu上运行play,可以从scala action获得java编译器,没有任何问题。也许您的设置有问题?只是尝试了
JavaCompiler=ToolProvider.getSystemJavaCompiler();System.out.println(“Java编译器:“+javaCompiler”)
来自
app/Global.java
中的
onStart
方法,在我的应用程序的类路径中使用
tools.jar
,即使返回
null
,听起来也不错。我建议将tools jar放在一个公共位置或使用jdk。
        URL[] urls = {file.toURI().toURL()};
        ClassLoader cl = URLClassLoader.newInstance(urls);
        cl.setPackageAssertionStatus("com.sun.tools.javac", true);
        return Class.forName(defaultJavaCompilerName, false, cl);