ContextClassLoader使用不当导致的"奇怪"现象

简介:

最近从一位同学那得知了一个奇怪的异常现象(和classloader相关), 问题一直没有解决, 所以趁周末有空搭建测试环境研究一下:

问题现象

该应用是服务型应用, 如果应用启动时初始化所有的spring bean, 那么会有如下的异常,反之运行时一点一点初始化spring bean则没有任何问题。(所以应用在线上没有使用fail fast模式,有一定风险)
_2015_08_11_6_58_17

个人分析

  • 异常比较底层, 所以把抛出异常的class(DirContextURLStreamHandler)反编译看了下。如下:
    _2015_08_11_7_10_52
  • 先了解了下该class的结构和用途:该类中clBindings和threadBindings是普通的map对象, 当执行ServletContext.getResource(resourceName).openConnection()方法后DirContextURLStreamHandler的get方法都会调用(基本可认为只要加载web应用下文件就会使用). 为什么这个方法调用会和异常堆栈联系在一起? 这里简单讲解下tomcat的加载应用中资源的逻辑, 当我们使用ServletContext.getResource获取该资源URL时,你可能看到如下的结果, 因为tomcat 使用了Java命名系统接口(jndi)来命名/操作应用下的资源:
    _2015_08_08_12_03_37
  • jndi这个协议的Handler是通过以下语句设置的(WebappLoader.java中):
    URL.setURLStreamHandlerFactory(new DirContextURLStreamHandlerFactory);
  • 而DirContextURLStreamHandlerFactory实现也比较简单,如果url的协议是jndi, 就由DirContextURLStreamHandler(这也是最终抛出异常的类)来进行处理。
    _2015_08_11_8_12_47

从异常中发现,加载webx中的uri.xml时抛出了异常

定位问题

_2015_08_11_7_10_52

  • 尝试在class中增加了断点。当抛出异常时, 上图中115行的result为nulll, 正常情况下result是有值的。
    出现异常时clBindings中包含的key是org.jboss.web.tomcat.tc5.WebCtxLoader$ENCLoader, 而currentCL(上下文classloader)是org.jboss.mx.loading.UnifiedClassLoader3, 而导致查询不到结果. 所以我开始怀疑,是否业务代码中将上下文的classloader给改掉了。而导致这里查询不到DirContext(web目录上下文对象).
  • 用btrace打印了所有调用Thread.setContextClassLoader(ClassLoader classloder)的点, 并且该方法参数的class是org.jboss.mx.loading.UnifiedClassLoader3的线程堆栈. 日志打印出来后,内容很多,但是稍微过滤后(堆栈前5 frame中包含alibaba or taobao关键字),可以最终只剩下几个可疑class:
  • com.taobao.hsf.route.strategy.groovy.GroovyRouteRuleParser.parse(GroovyRouteRuleParser.java:103(正常)
    _2015_08_11_8_25_03

这里在操作ContextClassLoader逻辑是: 取出->更改->还原(finally语句块)

  • com.taobao.agoo.open.OpenServiceFactory.init(OpenServiceFactory.java:57)(有问题)
    _2015_08_11_8_26_05

这里在操作ContextClassLoader逻辑是: 取出->更改

解决问题

  • 很明显了,只要在OpenServiceFactory.java中增加"还原"的操作就可以了。增加"还原"操作后,应用启动初始化所有bean正常, 且无异常抛出。

问题还原

  • OpenServiceFactory更改了ContextClassLoader,但是没有还原原有的ContextClassLoader这种写法很少见(我不确定代码这样写的原有),但这里确实导致了该应用启动时抛出的异常。
  • 应用启动抛出异常 真实的原因是 OpenServiceFactory的初始化比较早,导致后面初始化home.webx.xml(还有其他的xml)出现了加载不到的异常。如果OpenServiceFactory初始化比较晚,并且应用不需要加载web下的资源文件,那么也不会有问题。
  • 那为什么应用启动时,不初始化OpenServiceFactory就没有问题呢?因为该应用是服务型的应用,启动时已经初始化过了所需要的web目录下资源文件(例如: webx.xml, pipeline.xml等), 没有其他的资源文件需要加载(即使影响也肯能只影响修改了ContextClassLoader的线程), 所以不会导致这个问题出现。

classloader引起的问题很少见,问题出现后也不太容易排查和解决,这个场景相对是比较简单,只是这个异常比较"奇怪"而已

目录
相关文章
|
数据采集 自然语言处理 算法
如何使用Python的Gensim库进行自然语言处理和主题建模?
使用Gensim库进行Python自然语言处理和主题建模,包括:1) 安装Gensim;2) 导入`corpora`, `models`, `nltk`等相关模块;3) 对文本数据进行预处理,如分词和去除停用词;4) 创建字典和语料库;5) 使用LDA算法训练模型;6) 查看每个主题的主要关键词。代码示例展示了从数据预处理到主题提取的完整流程。
397 3
|
2月前
|
存储 缓存 算法
软考通关密钥:计算机系统核心原理全解剖——软件设计师必懂的底层逻辑
专为软考中级软件设计师打造,深入解析CPU架构、存储体系、进制转换、原码补码、浮点数、寻址方式、校验码、RISC/CISC、流水线、Cache、中断、I/O控制、总线及加密技术等核心知识点,结合真题剖析高频考点,构建计算机系统底层知识体系,提升应试与实践能力。
281 1
软考通关密钥:计算机系统核心原理全解剖——软件设计师必懂的底层逻辑
|
2月前
|
存储 安全 API
Typora介绍、安装、图床设置和使用
Typora是一款简洁高效的Markdown编辑器,支持实时预览、数学公式编辑、表格制作与多格式导出,适用于写作、学术与技术文档。本文详细介绍其安装、激活、主题设置、图床配置(PicGo+SM.MS/COS/OSS)及常用功能使用,助你高效搭建写作环境。
624 3
Typora介绍、安装、图床设置和使用
|
6月前
|
关系型数据库 MySQL 数据库
【赵渝强老师】数据库不适合Docker容器化部署的原因
本文介绍了在Docker中部署MySQL数据库并实现数据持久化的方法,同时分析了数据库不适合容器化的原因。通过具体步骤演示如何拉取镜像、创建持久化目录及启动容器,确保数据安全存储。然而,由于数据安全性、硬件资源争用、网络带宽限制及额外隔离层等问题,数据库服务并不完全适合Docker容器化部署。文中还提到数据库一旦部署通常无需频繁升级,与Docker易于重构和重新部署的特点不符。
395 18
【赵渝强老师】数据库不适合Docker容器化部署的原因
|
前端开发 JavaScript
electron ui框架
Electron是一个使用JavaScript, HTML和CSS等前端技术构建跨平台桌面应用程序的框架。
679 0
|
安全 应用服务中间件 Shell
网站在后台启用了https协议之后重新登录就不进去后台的解决方法
网站在后台启用了https协议之后重新登录就不进去后台的解决方法
|
开发者 Python
Python中的正则表达式:re模块详解与实例
Python中的正则表达式:re模块详解与实例
499 0
|
缓存 开发框架 前端开发
SpringCloud微服务实战——搭建企业级开发框架(四十一):扩展JustAuth+SpringSecurity+Vue实现多租户系统微信扫码、钉钉扫码等第三方登录
  如果我们自己的系统需要调用第三方登录,那么我们就需要实现单点登录客户端,然后跟需要对接的平台调试登录SDK。JustAuth是第三方授权登录的工具类库,对接了国外内数十家第三方登录的SDK,我们在需要实现第三方登录时,只需要集成JustAuth工具包,然后配置即可实现第三方登录,省去了需要对接不同SDK的麻烦。   JustAuth官方提供了多种入门指南,集成使用非常方便。但是如果要贴合我们自有开发框架的业务需求,还是需要进行整合优化。下面根据我们的系统需求,从两方面进行整合:一是支持多租户功能,二是和自有系统的用户进行匹配。
9381 56
SpringCloud微服务实战——搭建企业级开发框架(四十一):扩展JustAuth+SpringSecurity+Vue实现多租户系统微信扫码、钉钉扫码等第三方登录
|
监控 安全 网络安全
网络信息安全之信息系统安全保障
信息系统是用于采集、处理、存储、传输、分发和部署信息的整个基础设施、组织结构、人员和组件的总和。随着当前社会信息化程度的不断提高,各类信息系统越来越成为其所从属的组织机构生存和发展的关键因素,信息系统的安全风险也成为组织风险的一部分。同时,信息系统受来自于组织内部与外部环境的约束,信息系统的安全保障除了要充分分析信息系统本身的技术、业务、管理等特性,还要考虑这些约束条件所产生的要求。为了保障组织机构完成使命,系统安全管理人员必须针对信息系统面临的各种各样的风险制定相应的策略。
917 0