开发那点事系列二 - ClassLoader trouble shooting references

简介:          工作中需要解决一些servlet容器类加载器的问题,尤其是Jboss 4.x系列,比方说log4j版本冲突需要靠更改配置项Java2ClassLoadingCompliance,UseJBossWebLoader;ear包部署,出现NoSuchMethodError,NoSuchFieldError,NoClassDefFoundError等(二进制兼容错误)需要进行类隔

         工作中需要解决一些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. http://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. http://javarevisited.blogspot.com/2011/06/noclassdeffounderror-exception-in.html

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

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

目录
相关文章
|
2月前
|
存储 安全 前端开发
Web渗透-文件上传漏洞-上篇
文件上传漏洞常见于Web应用,因类型限制不严可致恶意文件执行。本文介绍前端检测、MIME类型、黑名单、.htaccess、空格、双写等多种绕过方式,并结合upload-labs靶场演示利用方法,提升安全防护认知。
348 1
Web渗透-文件上传漏洞-上篇
|
敏捷开发 测试技术 持续交付
探索自动化测试:从基础到高级
【10月更文挑战第35天】在软件质量的保证过程中,自动化测试以其高效和可重复性成为不可或缺的一环。本文旨在通过简明的语言和实际案例引导读者了解自动化测试的核心概念、工具选择与应用,以及如何实现从入门到精通的过渡。我们将一起探讨如何将自动化测试策略融入日常开发流程中,提升测试效率,同时确保产品质量。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
532 3
|
前端开发 JavaScript API
前端框架新探索:Svelte在构建高性能Web应用中的优势
【10月更文挑战第26天】近年来,前端技术飞速发展,Svelte凭借独特的编译时优化和简洁的API设计,成为构建高性能Web应用的优选。本文介绍Svelte的特点和优势,包括编译而非虚拟DOM、组件化开发、状态管理及响应式更新机制,并通过示例代码展示其使用方法。
351 2
|
算法 计算机视觉
图像处理之调整亮度与对比度
图像处理之调整亮度与对比度
336 6
|
Android开发
Launcher默认支持旋转
Launcher默认支持旋转
242 1
|
算法 搜索推荐 Java
基于SpringBoot+协同过滤算法的家政服务平台设计和实现(源码+LW+调试文档+讲解等)
基于SpringBoot+协同过滤算法的家政服务平台设计和实现(源码+LW+调试文档+讲解等)
|
监控 安全 Linux
【阿里云镜像】基于YUM方式构建Zabbix监控平台
【阿里云镜像】基于YUM方式构建Zabbix监控平台
797 1
【阿里云镜像】基于YUM方式构建Zabbix监控平台
|
分布式计算 Hadoop Java
PySpark数据分析基础:Spark本地环境部署搭建
PySpark数据分析基础:Spark本地环境部署搭建
1731 0
PySpark数据分析基础:Spark本地环境部署搭建
|
存储
ENVI_IDL: 创建HDF5文件并写入数据(以将Geotiff文件写入HDF文件为例) + 详细解析
ENVI_IDL: 创建HDF5文件并写入数据(以将Geotiff文件写入HDF文件为例) + 详细解析
359 0
|
数据可视化 JavaScript 前端开发
前端可视化大屏设置全屏模式方法
前端可视化大屏设置全屏模式方法
前端可视化大屏设置全屏模式方法
下一篇
oss云网关配置