用一点JAR手术修复Java类路径问题

时间:2013-02-01 10:18:31

标签: java jar classloader slf4j dll

我刚尝试测试使用Apache Camel 2.10.3的应用程序,并且在实例化DefaultCamelContext后立即获得以下异常:

java.lang.NoSuchMethodError: org.slf4j.Logger.trace(Ljava/lang/String;Ljava/lang/Object;)V
    at org.apache.camel.impl.DefaultPackageScanClassResolver.<init>(DefaultPackageScanClassResolver.java:70)
    at org.apache.camel.impl.DefaultCamelContext.<init>(DefaultCamelContext.java:222)

我确保slf4j-api-1.6.6(这是Camel 2.10.3附带的)在运行时类路径上。接下来,我怀疑我可能还有其他依赖项也使用过SLF4J,但这依赖于它的不同版本。所以我打开了Eclipse,并运行了org.slf4j.Logger的类型搜索。果然,我看到该类列在2个不同的JAR中:slf4j-api-1.6.6.jar(正如预期的那样!)和另一个第三方jar,{{1 }}

所以我打开了widget-lib-3.0.jar,看到SLF4J打包在里面就像这样:

widget-lib3.0.jar

没有办法说出它在这里使用的是什么版本的SLF4J,但是我愿意打赌它是一个早于1.6.x的版本,这是Camel 2.10.3想要的版本。

所以我最好的,稍微受过教育的猜测是,在运行时,JRE类加载器首先找到widget-lib-3.0/ com/ <Widget Lib's compiled classes> org/ slf4j/ spi/ ... impl/ ... <A bunch of SLF4J classes, like LoggerFactory.class, etc.> ,然后加载它,然后它们将加载Camel JAR及其依赖项。然后,当widget-lib-3.0.jar#org/slf4j/Logger调用SLF4J DefaultPackageScanClassResolver方法时,它没有找到SLF4J的1.6.6版本,而是找到了trace(String,Object)附带的任何版本,并且该方法/重载没有'存在。

我是否已离开基地?如果我离开基地,这对你意味着什么呢?如果我正在进行中,那么我提出的解决方案是在没有widget-lib-3.0.jar包的情况下重新进行JAR widget-lib-3.0.jar(不存在其他更现代的版本)。我的理论是org/slf4j,它是向后兼容的,将是唯一加载的SLF4J版本,然后将适用于两个JAR。有什么想法吗?提前谢谢。

3 个答案:

答案 0 :(得分:0)

  

“没有办法说出它在这里使用的SLF4J的版本,但我会   愿意打赌它是一个比1.6.x更早的版本   是Camel 2.10.3想要的......“

为什么不从widget-lib-3.0.jar反编译该类文件,看看是否存在所需的方法?

答案 1 :(得分:0)

你的方法是正确的。 SLF4J 1.x版本之间的API兼容。 (你顺便使用Maven吗?它旨在防止这种问题)。

什么是widget-lib?是否有不包含其依赖项的版本?如果有,你应该使用它。

答案 2 :(得分:0)

  

我是否正在离开基地?

没有。看起来你正在这里。

确认它的方法是在窗口小部件库JAR中获取org.sfl4j.Logger的副本,并使用javah查看它是否具有void trace(String, Object)方法。

确认后,有许多解决方案:

  • 最干净的解决方案是获取窗口小部件库的源代码,根据您需要的sfl4j版本重新编译它,并构建新版本的JAR而不在其中嵌入sfl4j。 (您可能需要修改窗口小部件库的源,但不太可能)。

  • 一个更简单的解决方案可能是确保您将更新的(并且应该是向后兼容的)slf4 API JAR放在类路径上的小部件库JAR之前。这样,小部件JAR中旧版本的slf4j将被较新的版本用“Camel”需要的额外方法“阴影”。