【问题标题】:Why do I keep getting NoSuchMethodError on LocationAwareLogger when running Jetty?为什么我在运行 Jetty 时总是在 LocationAwareLogger 上收到 NoSuchMethodError?
【发布时间】:2013-10-04 23:23:01
【问题描述】:

我正在尝试将 Jetty 服务器嵌入到我的自动化测试中,因此我在我的项目中添加了以下依赖项:

<dependency>
  <groupId>org.eclipse.jetty</groupId>
  <artifactId>jetty-servlet</artifactId>
  <version>7.6.13.v20130916</version>
  <scope>test</scope>
</dependency>

我正在使用 Jetty 7,因为 Web 应用程序使用 Java 6、Servlet 2.5。

但是,当我尝试启动嵌入式 Jetty 服务器时,我得到:

java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/Object;Ljava/lang/Throwable;)V
    at org.eclipse.jetty.util.log.JettyAwareLogger.log(JettyAwareLogger.java:607)
    at org.eclipse.jetty.util.log.JettyAwareLogger.warn(JettyAwareLogger.java:431)
    at org.eclipse.jetty.util.log.Slf4jLog.warn(Slf4jLog.java:69)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.setFailed(AbstractLifeCycle.java:204)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:74)

我一直试图找出问题所在,但到目前为止我采取的任何步骤都没有解决这个问题。以下是我到目前为止所做的列表:

  • 跟踪传递依赖以搜索不兼容的slf4j-api 版本
  • 尝试不同版本的slf4j-api(1.5.11、1.6.1、1.6.4、1.7.5)
  • 查看了 Jetty 7 的一些源代码,特别是 pom.xml,发现存在对 slf4j 1.6.1 的依赖项
  • 查看this similar question 并在尝试打印org.slf4j.spi.LocationAwareLoggerorg.slf4j.Marker 时得到null

我希望有人可以对这个问题提供新的见解。谢谢。

【问题讨论】:

  • 您是否尝试在 jetty-servlet 依赖项上为 slf4j 指定
  • jetty-servlet 似乎没有对 slf4j 的传递依赖,这看起来很奇怪。

标签: java maven jetty slf4j


【解决方案1】:

我敢打赌,您在 sl4j 罐子之间遇到过 compatibility problem。尝试检查最终工件的mvn dependency:tree 输出。也许你有一些sl4j jar 的两个不同版本,你无法预测哪个会先加载。尝试均衡所有sl4j 版本。


OP:请参考documentation on how I resolved this

【讨论】:

  • 我什至已经做到了依赖树中绝对没有 slf4j,以确保当我专门添加它时,所有传递依赖都已完全排除。
  • 如果根本没有sl4j jar,那么您将得到NoClassDefFoundError,因为JettyAwareLogger 包含对sl4j SPI 类的引用。因此,这些类在运行时存在。他们来自哪里?也许是你的容器lib 文件夹?或者你可能依赖一个重新打包的 jar,它已经包含 sl4j 类?
  • 你知道我有什么方法可以验证吗?到目前为止,我所做的是,因为我使用的是 Eclipse,所以在任何类中导入 LocationAwareLogger,然后尝试跟踪它以检查它是否从构建路径中的 slf4j jar 中导入。如果我对 slf4j 没有任何依赖关系,我将无法导入它,但正如您所注意到的,我没有得到 NoClassDefFoundError,我也一直试图故意提高它。
  • 1 使用-verbose:class 选项启动JVM 2 在Eclipse 中调试时在任何断点处停止并显示@ 987654339@ 查看。在其中输入org.slf4j.spi.LocationAwareLogger.class.getResource(org.slf4j.spi.LocationAwareLogger.class.getSimpleName() + ".class"),选择并按Display Result of Evaluating Selected Text。您会看到课程的来源。
  • 如果单独使用 jetty,请使用 $ java -jar start.jar --version 并查看服务器类路径。然后查看您的 webapp 的 WEB-INF/lib 树。最后,将独立码头中的 jetty.dump.start 设置为 true 以查看 webapp 类路径的转储。
【解决方案2】:

madheadanswer 上的信息非常有帮助,但我将记录我所做的详细信息,以供(将)遇到同样问题的其他人使用。

正如提到的答案所暗示的,这是slf4j jars 的问题。为了验证我做了以下事情:

  1. 对所有依赖于slf4j 的依赖项定义排除项。
  2. 遵循this suggestion 中的选项2。
    • 我编写了一个单元测试,其中 sysout 是我选择的字符串,并在该行定义了一个断点。
    • 然后我将测试作为 JUnit 测试进行调试,并打开显示视图
    • 我需要重新运行它,因为 Display Result of Evaluating Selected Text 一开始由于某种原因被禁用。
    • 我发现运行时仍然引用 slf4j 的 1.5.8 版本,无论我是否为它指定排除项,它仍然被添加到类路径中。
  3. 我正在处理的项目依赖于我也在处理的另一个项目(它是一个多 Maven 项目项目),它指定了对 slf4j-jdk14 1.5.8 的依赖关系,所以我只是将其更新为 1.6.1
    • 我必须在slf4j-jdk14 1.6.1 下指定排除slf4j-api,因为它指的是版本1.5.8,并添加对slf4j-api 1.6.1 的直接依赖。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 2020-02-15
    • 1970-01-01
    • 2013-12-23
    • 1970-01-01
    • 2019-11-25
    • 2015-06-14
    相关资源
    最近更新 更多