【问题标题】:Fixing Java classpath issue with a little JAR surgery通过一点 JAR 手术修复 Java 类路径问题
【发布时间】:2013-02-01 10:18:30
【问题描述】:

我刚刚尝试测试一个使用 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(如预期的那样!)和另一个 3rd 方 jar,widget-lib-3.0.jar

所以我打开了widget-lib3.0.jar,看到里面的 SLF4J 是这样打包的:

widget-lib-3.0/
    com/
        <Widget Lib's compiled classes>
    org/
        slf4j/
            spi/
                ...
            impl/
                ...
            <A bunch of SLF4J classes, like LoggerFactory.class, etc.>

没有办法知道它在这里使用的是什么版本的 SLF4J,但我敢打赌它是早于 1.6.x 的版本,这正是 Camel 2.10.3 想要的。

所以我最好的,稍微受过教育的猜测是,在运行时,JRE 类加载器首先找到widget-lib-3.0.jar#org/slf4j/Logger,加载它,然后然后他们去加载 Camel JAR 及其依赖项。然后,当DefaultPackageScanClassResolver 调用 SLF4J trace(String,Object) 方法时,它没有找到 1.6.6 版本的 SLF4J,而是找到了 widget-lib-3.0.jar 附带的任何版本,并且该方法/重载不存在。

我是否正在离开基地?如果我不在基地,这对你意味着什么,所以?如果我走上了正轨,那么我建议的解决方案是重新 JAR widget-lib-3.0.jar 而不包含 org/slf4j 包(不存在其他更现代的版本)。我的理论是向后兼容的slf4j-api-1.6.6 将是唯一被加载的 SLF4J 版本,然后适用于两个 JAR。有什么想法吗?提前致谢。

【问题讨论】:

    标签: java jar classloader slf4j dll


    【解决方案1】:

    我是否正在离开基地?

    没有。看来您在这里步入正轨。

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

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

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

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

    【讨论】:

      【解决方案2】:

      “没有办法知道它在这里使用的是什么版本的 SLF4J,但我会 愿意打赌它是早于 1.6.x 的版本, 是 Camel 2.10.3 想要的”...

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-05-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-11
          • 1970-01-01
          相关资源
          最近更新 更多