閱讀466 返回首頁    go 阿裏雲 go 技術社區[雲棲]


開發那點事係列二 - ClassLoader trouble shooting references

         工作中需要解決一些servlet容器類加載器的問題,尤其是Jboss 4.x係列,比方說log4j版本衝突需要靠更改配置項Java2ClassLoadingCompliance,UseJBossWebLoader;ear包部署,出現NoSuchMethodError,NoSuchFieldError,NoClassDefFoundError等(二進製兼容錯誤)需要進行類隔離(在 JVM加上-XX:+TraceClassLoading  -XX:+TraceClassUnloading分析完類的加載卸載verbose)等。除此之外,還有一種ClassLoader問題比較常見。即:如果類庫提供了 SPI 接口,並且利用線程上下文類加載器來加載 SPI 實現的 Java 類,有可能會找不到 Java 類。如果出現了 NoClassDefFoundError異常(初始類加載器,定義類加載器問題),則可以先檢查當前線程的上下文類加載器是否正確。通過 Thread.currentThread().getContextClassLoader()就可以得到該類加載器。該類加載器應該是該模塊對應的類加載器。如果不是的話,可以首先通過 class.getClassLoader()來得到模塊對應的類加載器,再通過 Thread.currentThread().setContextClassLoader()來設置當前線程的上下文類加載器。關於上下文加載器,一個顯著的使用場景是javax.xml.parsers.DocumentBuilderFactory類中的newInstance方法,跟進去後代碼具體如下:

 /*
     * Try to find provider using Jar Service Provider Mechanism
     *
     * @return instance of provider class if found or null
     */
    private static Object findJarServiceProvider(String factoryId)
        throws ConfigurationError
    {
        String serviceId = "META-INF/services/" + factoryId;
        InputStream is = null;

        // First try the Context ClassLoader
        ClassLoader cl = ss.getContextClassLoader();
        boolean useBSClsLoader = false;
        if (cl != null) {
            is = ss.getResourceAsStream(cl, serviceId);

            // If no provider found then try the current ClassLoader
            if (is == null) {
                cl = FactoryFinder.class.getClassLoader();
                is = ss.getResourceAsStream(cl, serviceId);
                useBSClsLoader = true;
            }
        } else {
            // No Context ClassLoader, try the current ClassLoader
            cl = FactoryFinder.class.getClassLoader();
            is = ss.getResourceAsStream(cl, serviceId);
            useBSClsLoader = true;
        }

        if (is == null) {
            // No provider found
            return null;
        }

        if (debug) {    // Extra check to avoid computing cl strings
            dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl);
        }

        BufferedReader rd;
        try {
            rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        }
        catch (java.io.UnsupportedEncodingException e) {
            rd = new BufferedReader(new InputStreamReader(is));
        }

        String factoryClassName = null;
        try {
            // XXX Does not handle all possible input as specified by the
            // Jar Service Provider specification
            factoryClassName = rd.readLine();
            rd.close();
        } catch (IOException x) {
            // No provider found
            return null;
        }

        if (factoryClassName != null && !"".equals(factoryClassName)) {
            dPrint("found in resource, value=" + factoryClassName);

            // Note: here we do not want to fall back to the current
            // ClassLoader because we want to avoid the case where the
            // resource file was found using one ClassLoader and the
            // provider class was instantiated using a different one.
            return newInstance(factoryClassName, cl, false, useBSClsLoader);
        }

        // No provider found
        return null;
    }

最後,將自己曾經參考過的文獻資料分享給大家,希望能對大家有所幫助。

1. https://community.jboss.org/wiki/ClassLoadingConfiguration

2. https://docs.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/4.2/html/Server_Configuration_Guide/Class_Loading_and_Types_in_Java-Inside_the_JBoss_Class_Loading_Architecture.html

3. https://community.jboss.org/wiki/JBossClassLoadingUseCases

4. https://community.jboss.org/wiki/ClassLoadingConfiguration

5. https://community.jboss.org/wiki/EnableClassloaderLogging

6. https://community.jboss.org/wiki/ClassLoadingConfiguration.pdf;jsessionid=EAFBE16C312C6DCCAF6F42840D80F4F6

7. https://community.jboss.org/wiki/SeparatingApplicationLogs

8. https://javarevisited.blogspot.com/2011/06/noclassdeffounderror-exception-in.html

9. https://www.artima.com/insidejvm/blurb.html

10. https://articles.qos.ch/classloader.html

最後更新:2017-04-02 22:16:24

  上一篇:go Android界麵開發推薦顏色
  下一篇:go ITEXT實例學習與研究(三) 之 頁邊距的設計 摘要