Log4j 线程死锁 - 案例研究

  • 主要观点:描述了影响 WebLogic Portal 10.0 生产环境的 Apache Log4j 线程竞争问题的根本原因分析与解决,强调开发和支持 Java EE 应用时了解 Java 类加载器的重要性。
  • 关键信息

    • 环境:Java EE 服务器为 Oracle Weblogic Portal 10.0,操作系统为 Solaris 10,JDK 为 Oracle/Sun HotSpot JVM 1.5,日志 API 为 Apache Log4j 1.2.15,RDBMS 为 Oracle 10g,平台类型为 Web 门户。
    • 工具:Quest Foglight for Java(监控和警报)、Java VM 线程转储(线程竞争分析)。
    • 问题:WebLogic 生产环境性能严重下降,Foglight 警报显示线程利用率大幅上升至 400 上限。
    • 事实收集与验证:包括客户端影响高、近期平台有变化(部署涉及内容和库更改)、近期流量无增加、问题在部署后出现、重启 Weblogic 服务器未解决问题、回滚部署变化可解决问题等。
    • 线程转储分析:发现 250 个线程卡在特定执行路径,等待获取 Apache Log4j 对象监视器的锁,推测是 Log4j 代码的同步块导致线程竞争条件。
    • Log4j 1.2.15 代码审查:Category.callAppenders()使用的同步块在高并发负载下易导致严重线程竞争条件,可使用可重入读写锁更合适。
    • 根本原因:近期部署移除了子类加载器级别的一些 Log4j 库及相关策略,导致 Log4j 调用移至父类加载器,增加了 Log4j 组件的并发度,引发线程竞争/死锁问题。
    • 解决措施:回滚重构并将 Log4j 调用分回父类和子类加载器,或将某些记录器的日志级别从 DEBUG 降低到 WARNING。
  • 重要细节

    • 通过简单的 Solaris OS 命令 kill -3 <Java PID>生成 Weblogic 服务器的线程转储快照,并从 Weblogic 标准输出日志文件中提取数据。
    • 对线程栈跟踪进行详细剖析,以更好地理解线程竞争条件。
    • 提到未来可能升级到 Apache Log4j 2 以解决线程竞争和可扩展性问题。

总之,该案例研究通过详细的分析和解决过程,展示了线程竞争问题对生产环境的影响以及解决此类问题的方法和重要性。

阅读 4
0 条评论