使用log4j自定义布局类运行应用程序时jBoss上的java.lang.LinkageError

时间:2010-03-19 17:59:51

标签: java jboss log4j classloader

我正在尝试按照my previous post中的描述为Log4J配置自定义布局类。该类使用java.util.regex.Matcher来识别日志消息中的潜在信用卡号。它在单元测试中也很有效,也适用于包含单个servlet的最小Web应用程序。但是,当我尝试使用JBoss中的应用程序部署它时,我收到以下错误:

--- MBEANS THAT ARE THE ROOT CAUSE OF THE PROBLEM ---
ObjectName: jboss.web.deployment:war=MyWebApp-2010_02-SNAPSHOT.war,id=476602902
  State: FAILED
  Reason: java.lang.LinkageError: java/util/regex/Matcher

我甚至无法找到关于此错误形式的任何信息 - 通常LinkageError似乎显示“加载器约束违规”消息,如here中所示。

技术细节:我们使用JBoss 4.2,Java 5,Log4J 1.2.12。我们在.ear中部署我们的应用程序,其中包含(以及其他)上面提到的.war文件,以及单独的jar文件中的自定义布局类(我们称之为Commons)。我们覆盖jboss-log4j.xml中的默认设置,我们自己的log4j.properties位于不同的文件夹中,该文件夹在启动时添加到类路径中,并通过Sapient's Carbon framework提供。

更新到@ skaffman的回答:

我们有一个单独的log4j.properties文件的原因是Sapient Carbon传播的方案。这基本上将配置和数据文件与应用程序服务器环境分离,以便可以通过Carbon的查找功能访问它们,并且可以将它们存储在应用程序服务器外部的目录中。我们继承了这个设置,我们讨厌它,因为它导致我们在部署,类路径问题等方面遇到很多麻烦,因为它不符合JEE约定。我们的目标是从长远来看摆脱它,但它需要时间: - (

即使单独的log4j.properties文件不是最佳实践,但它确实有效。它已在我们的应用程序中运行多年,我也可以使用包含单个servlet(不使用Sapient Carbon)的极简主义Web应用程序。如果将log4j.properties放入类路径中,则Log4J会在启动Web应用程序时正确读取它,并相应地重新配置日志记录。

更新#2:一个有趣的发现是,Matcher甚至没有在MyWebApp中使用,只在Commons模块中使用(和另一个模块,在一个单独的jar中)。在Commons中,之前已经在一个名为StringHelper的类中使用它,它由MyWebApp通过其他模块间接使用。

我想这排除了由不同类加载器加载的两个不同Matcher类版本的可能性。所以我唯一剩下的猜测是,当从jar和战争中使用Matcher时,Matcher被两个不同的类加载器加载,然后尝试从一个传递到另一个。这由Frank Kieviet's excellent article解释。但是,我认为这样的设置会导致“加载器约束违规”,而不是这种形式的错误。

更新#3:如果我将this appender (example 3.8)添加到jboss-log4j.xml,则错误消失,服务器运行正常: - o这显然需要加载log4j .jar,因为此设置要求jar存在于服务器lib目录中。如果我将appender类型更改为org.jboss.logging.appender.FileAppender,并将日志级别设置为WARN,也会生成空ucl.log文件。这可能适合作为临时解决方法,但我仍然渴望完全理解这里发生了什么。

此错误消息的含义是什么,以及如何正确修复?


后记

经过漫长的等待,我终于从日志记录过程中消除了Carbon,并将我们的日志配置迁移到server/conf/jboss-log4j.xml。这要求我在server/lib目录中的单独jar中发布自定义日志过滤器类。在此之后,类加载再次起作用,没有上面更新#3中描述的解决方法: - )

2 个答案:

答案 0 :(得分:1)

您要么有两类不同的签名,但在您的环境中使用相同的路径,或者您根据j.u.r.Matcher的另一个签名进行编译。由于这是标准的Java API,我认为您应该检查源代码和编译目标以及JBoss安装的JVM运行时版本。

修改

在排除之后,我确定,管理appender并尝试加载使用自定义布局的appender的类加载器(服务器)无法看到自定义布局类实例。所以你有两个选择:

  1. 将自定义布局JAR与log4j一起部署到服务器的lib目录。
  2. 将log4j与您的应用程序一起部署,并将应用程序与您自己的类加载器隔离(jboss-app.xml):
  3. <jboss-app> <loader-repository> com.myapplication:loader=MyClassLoader <loader-repository-config>java2ParentDelegation=false</loader-repository-config </loader-repository> </jboss-app>

    我希望,问题会消失。

答案 1 :(得分:1)

我的第一反应是,在JBoss中,不可能像这样覆盖log4j配置。 JBoss不允许log4j找到自己的配置,正如conf/jboss-log4j.xmlconf/jboss-service.xml中指定conf/jboss-log4j.xml的位置一样。

据我所知,给定JBoss服务器中的所有log4j配置必须集中到一个文件中,通常是log4j.properties

作为测试,您是否尝试将conf/jboss-log4j.xml的内容移动到现有的{{1}}文件中?如果这样可以正常工作,那么问题几乎肯定是由于您尝试覆盖log4j引起的。话虽如此,如果jboss / log4j很脆弱,我会感到惊讶,但在某些情况下,它可能会拒绝这一点。