通过错误堆栈信息和源码分析错误来源

 

本文副标题:解决 NoSuchMethodError 异常

java.lang.NoSuchMethodError: org.slf4j.MDC.getCopyOfContextMap()Ljava/util/Map

-------------------------------------------------------

 

今天在一台机器上配置完 spring-activemq 后,可以无障碍的运行测试代码。但是,完全相同的代码提交后在另一台机器死活跑不通。主要的错误堆栈信息如下

Caused by: java.lang.NoSuchMethodError: org.slf4j.MDC.getCopyOfContextMap()Ljava/util/Map;
	at org.apache.activemq.util.MDCHelper.getCopyOfContextMap(MDCHelper.java:30)
	at org.apache.activemq.thread.PooledTaskRunner.<init>(PooledTaskRunner.java:42)

 

Java.lang.NoSuchMethodError 的 javadoc 注释如下:

/**
 * Thrown if an application tries to call a specified method of a 
 * class (either static or instance), and that class no longer has a 
 * definition of that method. 
 * <p>
 * Normally, this error is caught by the compiler; this error can 
 * only occur at run time if the definition of a class has 
 * incompatibly changed. 
 *
 * @author  unascribed
 * @version %I%, %G%
 * @since   JDK1.0
 */

 

通过注释( this error can only occur at run time if the definition of a class has incompatibly changed. )可以初步推断是因为版本不兼容导致的。 

 

NOTE: 错误信息里方法名后的 Ljava/util/Map 代表的是该方法的返回值类型。

 

再结合所缺失方法(org.slf4j.MDC.getCopyOfContextMap)的 Javadoc:

 /**
   * Return a copy of the current thread's context map, with keys and values of
   * type String. Returned value may be null.
   * 
   * @return A copy of the current thread's context map. May be null.
   * @since 1.5.1
   */
  public static Map getCopyOfContextMap() {

 

从 @since 1.5.1 可以看出,该方法需要高于1.5.1 的 slf4j 版本。

 

在工程 pom 下查看所依赖的 slf4j 版本发现所使用的是 1.5.11,从版本看是没有问题的。那么错误究竟从哪儿来的?从同事那里知道之前碰到过这个问题,当时解决的方法是将 JBoss 的版本从5.0.0换到了5.1.0。试了一下,用这个办法确实可以解决问题。但是,我并不满足于只是解决了问题,如果只是这样,那么前面的分析都白费了。

 

我想验证的是:Jboss 5.0.0 依赖的 sfl4j 版本是1.5.1之前的,而jboss 5.1.0 依赖的是slf4j 1.5.1之后的某个版本。经过一翻对比,确实证实了这个猜测。以下来自 jboss 根目录下的 jar-versions.xml : 

 

jboss 5.0.0 用的 slf4j 是 1.5.0

<jar name="slf4j-api.jar" specVersion="5.0.0.GA" specVendor="JBoss (http://www.jboss.org/)" specTitle="JBoss" implVersion="1.5.0" implVendor="JBoss Inc." implTitle="slf4j-api" implVendorID="http://www.jboss.org/" implURL="http://www.jboss.org/" sealed="false" md5Digest="d0841573796aa6b6dcf311e7e8f07a95"/>

 jboss 5.1.0 用的 slf4j 是 1.5.6

 <jar name="slf4j-api.jar" specVersion="5.1.0.GA" specVendor="JBoss (http://www.jboss.org/)" specTitle="JBoss" implVersion="1.5.6" implVendor="JBoss Inc." implTitle="slf4j-api" implVendorID="http://www.jboss.org/" implURL="http://www.jboss.org/" sealed="false" md5Digest="63720afbf77db737e305c85388302650"/>
 

通过这次的分析也可以看出,工程中依赖的 jar 包如果跟 jboss 自身依赖的 jar 版本冲突,会优先使用 jboss 的 jar。

 

最后,这个案例带给我的最大收获是通过错误堆栈信息以及源码可以更快的分析出错误的来源。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值