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複製進去,問題就沒了。

 

這樣就沒有報空指針錯誤了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章