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

运行带有log4j自定义布局类的应用程序时jBoss上的java.lang.LinkageError,java,jboss,log4j,classloader,Java,Jboss,Log4j,Classloader,我正在尝试将自定义布局类配置为Log4J,如中所述。该类使用java.util.regex.Matcher来识别日志消息中的潜在信用卡号。它可以在单元测试中完美地工作,也可以在包含单个servlet的最小web应用程序中工作。但是,当我尝试在JBoss中使用我们的应用程序部署它时,我得到以下错误: --- MBEANS THAT ARE THE ROOT CAUSE OF THE PROBLEM --- ObjectName: jboss.web.deployment:war=MyWebApp-

我正在尝试将自定义布局类配置为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会显示一条“loader Constraint violation”消息,如中所示

技术细节:我们使用JBoss4.2、Java5、Log4J1.2.12。我们将应用程序部署在一个.ear文件中,其中包含(除其他文件外)上述.war文件,并将自定义布局类部署在一个单独的jar文件中(我们称之为Commons)。我们使用位于不同文件夹中的
log4j.properties
覆盖
jboss-log4j.xml
中的默认设置,该属性在启动时添加到类路径,并通过提供

更新@skaffman的答案:

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

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

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

我猜这排除了由不同类加载器加载两个不同Matcher类版本的可能性。因此,我唯一剩下的猜测是,Matcher在jar和war中使用时,由两个不同的类加载器加载,然后试图从一个类传递到另一个类。这是由解释的。但是,我相信这样的setup将导致“加载程序约束冲突”,而不是这种形式的错误

更新#3:如果我添加到jboss-log4j.xml,错误就会消失,服务器运行也会很好:-o这显然与加载log4j.jar有关,因为这个设置要求jar出现在服务器lib目录中。如果我将appender类型更改为
org.jboss.logging.appender.FileAppender,并将日志级别设置为
WARN
,这将导致一个空的
ucl.log
文件。这可能适合作为临时解决方法,但我仍然渴望完全了解这里发生的情况

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


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

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

编辑:

我敢肯定,在排除这种可能性之后,管理appender并尝试加载使用自定义布局的appender的类加载器(服务器)将看不到自定义布局类实例。所以你有两个选择:

  • 将自定义布局JAR与log4j一起部署到服务器的lib目录
  • 将log4j与应用程序一起部署,并使用自己的类加载器(jboss app.xml)隔离应用程序:
  • 
    com.myapplication:loader=MyClassLoader
    
    java2parentdelegion=false我的第一反应是,在JBoss中,不可能像那样覆盖log4j配置。JBoss不允许log4j定位自己的配置,因为它通常会在
    conf/JBoss-log4j.xml
    中指定
    conf/JBoss-service.xml
    的位置

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


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

    这是我已经知道的。。。不过还是要谢谢你。你会把log4j和EAR/WAR一起部署吗?当您将单个布局JAR移动到容器的lib目录时会发生什么?在加载布局类时,匹配器可能是第一个失败点。如果不使用EAR/WAR部署log4j,则父类加载器的类实例可能无法加载布局,因为加载器无法看到JAR。也许试着和你一起部署log4j