Arthas实践--排查Spring Boot应用NoSuchMethodError
前言
有时spring boot应用会遇到java.lang.NoSuchMethodError
的问题,下面以具体的demo来说明怎样利用arthas来排查。
Demo: https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-NoSuchMethodError
在应用的main函数里catch住异常,保证进程不退出
很多时候当应用抛出异常后,进程退出了,就比较难排查问题。可以先改下main函数,把异常catch住:
public static void main(String[] args) throws IOException { try { SpringApplication.run(DemoNoSuchMethodErrorApplication.class, args); } catch (Throwable e) { e.printStackTrace(); } // block System.in.read(); }
Demo启动之后,抛出的异常是:
java.lang.NoSuchMethodError: org.springframework.core.annotation.AnnotationAwareOrderComparator.sort(Ljava/util/List;)V at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:394) at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:383) at org.springframework.boot.SpringApplication.initialize(SpringApplication.java:249) at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:225) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) at com.example.demoNoSuchMethodError.DemoNoSuchMethodErrorApplication.main(DemoNoSuchMethodErrorApplication.java:13)
显然,异常的意思是AnnotationAwareOrderComparator
缺少sort(Ljava/util/List;)V
这个函数。
安装arthas
参考:https://alibaba.github.io/arthas/install-detail.html
使用sc命令查找类所在的jar包
应用需要抛出了异常,但是进程还没有退出,我们用arthas来attach上去。比如在mac下面:
./as.sh
然后选择com.example.demoNoSuchMethodError.DemoNoSuchMethodErrorApplication
进程。
再执行sc命令来查找类:
$ sc -d org.springframework.core.annotation.AnnotationAwareOrderComparator class-info org.springframework.core.annotation.AnnotationAwareOrderComparator code-source /Users/hengyunabc/.m2/repository/org/springframework/spring/2.5.6.SEC03/spring-2.5.6.SEC03.jar name org.springframework.core.annotation.AnnotationAwareOrderComparator isInterface false isAnnotation false isEnum false isAnonymousClass false isArray false isLocalClass false isMemberClass false isPrimitive false isSynthetic false simple-name AnnotationAwareOrderComparator modifier public annotation interfaces super-class +-org.springframework.core.OrderComparator +-java.lang.Object class-loader +-sun.misc.Launcher$AppClassLoader@5c647e05 +-sun.misc.Launcher$ExtClassLoader@689e3d07 classLoaderHash 5c647e05 Affect(row-cnt:1) cost in 41 ms.
可以看到AnnotationAwareOrderComparator
是从spring-2.5.6.SEC03.jar
里加载的。
使用jad查看反编绎的源代码
下面使用jad命令来查看AnnotationAwareOrderComparator
的源代码
$ jad org.springframework.core.annotation.AnnotationAwareOrderComparator ClassLoader: +-sun.misc.Launcher$AppClassLoader@5c647e05 +-sun.misc.Launcher$ExtClassLoader@689e3d07 Location: /Users/hengyunabc/.m2/repository/org/springframework/spring/2.5.6.SEC03/spring-2.5.6.SEC03.jar /* * Decompiled with CFR 0_132. */ package org.springframework.core.annotation; import java.lang.annotation.Annotation; import org.springframework.core.OrderComparator; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; public class AnnotationAwareOrderComparator extends OrderComparator { protected int getOrder(Object obj) { Order order; if (obj instanceof Ordered) { return ((Ordered)obj).getOrder(); } if (obj != null && (order = obj.getClass().getAnnotation(Order.class)) != null) { return order.value(); } return Integer.MAX_VALUE; } } Affect(row-cnt:1) cost in 286 ms.
可见,AnnotationAwareOrderComparator
的确没有sort(Ljava/util/List;)V
函数。
排掉依赖,解决问题
从上面的排查里,可以确定
AnnotationAwareOrderComparator
来自spring-2.5.6.SEC03.jar
,的确没有sort(Ljava/util/List;)V
函数。
所以,可以检查maven依赖,把spring 2的jar包排掉,这样子就可以解决问题了。
总结
- 仔细看
NoSuchMethodError
的异常信息,了解是什么类缺少了什么函数 - 利用arthas来查找类,反编绎源码,确认问题
链接
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Activiti对接业务表实现自定义用户和用户组
声明:Activiti版本5.22.0。 Activiti在初始化时会生成act_id_*系列与用户、用户组相关的表,但在实际业务中,我们系统可能初期并没有接入工作流,后期接入时就涉及到如何将现有业务表中的用户与Activiti进行对接,本文即简单介绍下思路。 1、自定义实现Activiti用户管理接口 自定义类CustomUserEntityManagerFactory实现SessionFactory接口,重写getSessionType和openSession方法,核心代码如下: import org.activiti.engine.impl.interceptor.Session; import org.activiti.engine.impl.interceptor.SessionFactory; import org.activiti.engine.impl.persistence.entity.UserIdentityManager; import org.springframework.beans.factory.annotation.Autowired; import ...
- 下一篇
php 日志库获取调用方的代码文件地址和代码行数
在使用其他语言的打印日志的时候,经常能看到打印日志时带上文件地址和代码行数,对于调试和查找问题非常方便,但是 php 日志库里则很少见到这个功能,但这个功能还是可以实现的。 关键点就是用 php 的 debug_backtrace 函数 先看个例子 test.php function test() { print_r(debug_backtrace()); } test(); 输出 Array ( [0] => Array ( [file] => /path/test.php [line] => 7 [function] => test ) ) debug_backtrace 能获取整个调用链,所以,我们的日志库就可以根据这一条实现在日志中带上文件和行号的功能 function xlog(string $lv, string $format, ...$args) { $log = "%s\t%s:%s\t%s" . PHP_EOL; $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); return...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2全家桶,快速入门学习开发网站教程
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8编译安装MySQL8.0.19
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2配置默认Tomcat设置,开启更多高级功能