zoukankan      html  css  js  c++  java
  • ToolProvider.getSystemJavaCompiler()方法空指针的排坑

    起因:

    我在做一个编译Java代码的功能,基本写的差不多了,我就想把它打包部署到我服务器上跑一跑,但是这不做不知道,一做果然就出了问题。我在IDEA上跑一点问题都没有,但是打包成Jar后,后台就显示空指针异常。

    排坑:(这里解决办法仅供参考)

    Maven打包是没问题的,而且Jar包也能正常跑,说明我的Maven设置和Spring依赖问题应该是没问题的,而经过我一番检查,空指针出现在:

    //获得javacompile实例
     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

    我都蒙了,因为这个是Java本身提供的方法,为啥获取不到JavaCompiler。于是我进一步查了这个的源代码:

    public static JavaCompiler getSystemJavaCompiler() {
            return instance().getSystemTool(JavaCompiler.class, defaultJavaCompilerName);
        }

    好像看不出啥,在往下:

    private <T> T getSystemTool(Class<T> clazz, String name) {
            Class<? extends T> c = getSystemToolClass(clazz, name);
            try {
                return c.asSubclass(clazz).newInstance();
            } catch (Throwable e) {
                trace(WARNING, e);
                return null;
            }
        }

    还是看不出啥,再进去一层:

    private <T> Class<? extends T> getSystemToolClass(Class<T> clazz, String name) {
            Reference<Class<?>> refClass = toolClasses.get(name);
            Class<?> c = (refClass == null ? null : refClass.get());
            if (c == null) {
                try {
                    c = findSystemToolClass(name);
                } catch (Throwable e) {
                    return trace(WARNING, e);
                }
                toolClasses.put(name, new WeakReference<Class<?>>(c));
            }
            return c.asSubclass(clazz);
        }

    查了一个get方法,还是没啥头绪,再看findSystemToolClass()

     
    private static final String[] defaultToolsLocation = { "lib", "tools.jar" };
    private Class<?> findSystemToolClass(String toolClassName)
            throws MalformedURLException, ClassNotFoundException
        {
            // try loading class directly, in case tool is on the bootclasspath
            try {
                return Class.forName(toolClassName, false, null);
            } catch (ClassNotFoundException e) {
                trace(FINE, e);
    
                // if tool not on bootclasspath, look in default tools location (tools.jar)
                ClassLoader cl = (refToolClassLoader == null ? null : refToolClassLoader.get());
                if (cl == null) {
                    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);
    
                    // if tools not found, no point in trying a URLClassLoader
                    // so rethrow the original exception.
                    if (!file.exists())
                        throw e;
    
                    URL[] urls = { file.toURI().toURL() };
                    trace(FINE, urls[0].toString());
    
                    cl = URLClassLoader.newInstance(urls);
                    refToolClassLoader = new WeakReference<ClassLoader>(cl);
                }
    
                return Class.forName(toolClassName, false, cl);
            }
        }

    看到加粗斜体的地方似乎有点感觉了,但是我还是没太想通问题在哪,我找了找百度,原来这么多人跟我遇到了一样的问题,最早的一篇博客还是09年写的。。

    原来这里首先是Java通过System.getProperty()获得环境变量,然后在找lib下面的tools.jar,这个tool.jar里面就有JavaCompiler,随后我找了发现jre里面并没有这个包,但是jdk里面有。于是我把jdk目录下的tool.jar复制到了jre下,但是仍然不行,这时候我估计我可能是我的Java环境变量的设置问题,于是我检查了一遍,但是java命令和javac命令都没问题。。。而且我打印System。getProperty("java.home")也跟本身电脑设置的JAVA_HOME有点不同,有点玄学。。

    最后我总结出两个解决办法:

    一个就是网上的复制tool.jar的方法,也就是把jre目录下面缺的包补上。但是这种在我这没起作用

    另一个是我自己的土办法,我手动调用jre/bin下面的java.exe 来运行这个jar包,当然提前也是需要把tool.jar复制进去,问题就没了。

     

    这样就没有报空指针错误了。

  • 相关阅读:
    ElementUI Form 表单
    ElementUI 快速入门
    您即将提交的信息不安全
    pandas excel合并去重
    openpyxl刷新透视表
    安装kube-prometheus
    多个py文件生成一个可运行exe文件
    Locust关联和参数化
    使用Docker运行locust
    Python locust阶段压测
  • 原文地址:https://www.cnblogs.com/Yintianhao/p/11056006.html
Copyright © 2011-2022 走看看