zoukankan      html  css  js  c++  java
  • ToolProvider.getSystemJavaCompiler() Return NULL!

    《Java深度历险》中有如下这么一个例子,是介绍如何来动态编译Java代码的,这种情况常见于编程竞赛场景,选手上传自己的代码到网站上,然后网站会来编译上传的代码。

    import java.io.IOException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.util.Arrays;
    import java.util.List;

    import javax.tools.JavaCompiler;
    import javax.tools.SimpleJavaFileObject;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    import javax.tools.JavaCompiler.CompilationTask;

    /**
    *
    @author YuFa
    *
    */
    public class CompilerTest {

    public static void main(String[] args) throws Exception {
    String source = "public class Main {" +
    "public static void main(String[] args) {" +
    "System.out.println(\"Hello World!\");" +
    "} " +
    "}";


    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
    StringSourceJavaObject sourceObject = new CompilerTest.StringSourceJavaObject("Main", source);
    List<StringSourceJavaObject> fileObjects = Arrays.asList(sourceObject);
    CompilationTask task = compiler.getTask(null, fileManager, null, null, null, fileObjects);

    boolean result = task.call();
    if (result) {
    System.out.println("Compile succeeded!");
    } else {
    System.out.println("Compile failed!");
    }
    }

    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;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    return content;
    }
    }
    }


    注意编译上面代码是需要JRE6的,因为JavaCompiler等类都是在JDK6中提供的。当我运行上面代码的时候,结果却抛出了null pointer exception. 问题出在如下这行代码...

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

    ToolProvider.getSystemJavaCompiler()返回的是NULL,因此在调用compiler.getStandardFileManager(null, null, null)的时候抛出了null pointer exception. 

    为啥会这样呢?查看了下ToolProvider的源代码,发现如下这么一段....

    private static final String[] defaultToolsLocation
                = { "lib", "tools.jar" };
    private static Class<?> findClass()
    throws MalformedURLException, ClassNotFoundException
    {
    try {
    return enableAsserts(Class.forName(defaultJavaCompilerName, false, null));
    } catch (ClassNotFoundException e) {
    // ignored, try looking else where
    }
    File file = new File(System.getProperty("java.home"));
    if (file.getName().equalsIgnoreCase("jre"))
    file = file.getParentFile();
    for (String name : defaultToolsLocation)
    file = new File(file, name);
    URL[] urls = {file.toURI().toURL()};
    ClassLoader cl = URLClassLoader.newInstance(urls);
    cl.setPackageAssertionStatus("com.sun.tools.javac", true);
    return Class.forName(defaultJavaCompilerName, false, cl);
    }


    我已经设置了JAVA_HOME环境变量,指向了我的JRE安装目录C:\Java\jre6, 注意查找文件的代码...

    for (String name : defaultToolsLocation)
    file = new File(file, name);

    也就是说会查找目录C:\Java\jre6\lib\tools.jar 

    但是注意的是tools.jar并不在jre中,而是在jdk安装目录下,因此我手动把这个jar文件从jdk目录下拷贝到了jre目录下,再次运行上面的代码就没有问题了!同时注意到在代码工程目录下生成了一个名为Main.class的文件,这个确实说明了动态类Main已经编译成功了!

  • 相关阅读:
    文件包含漏洞
    命令执行漏洞详解
    CSRF跨站请求伪造
    XSS跨站脚本攻击详解
    SQL盲注
    字符型注入、数字型注入、搜索型注入
    AWVS13扫描类型profile_id对照表
    Cobalt Strike 和 Metasploit Framework 联动
    msf常用命令
    上传嵌入式python环境进行渗透测试
  • 原文地址:https://www.cnblogs.com/fangwenyu/p/2209051.html
Copyright © 2011-2022 走看看