查看原文
其他

深入Spring Boot:利用Arthas排查NoSuchMethodError

横云断岭 横云断岭的专栏 2019-06-27

前言

有时spring boot应用会遇到 java.lang.NoSuchMethodError的问题,下面以具体的demo来说明怎样利用arthas来排查。

Demo: https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-NoSuchMethodError

在应用的main函数里catch住异常,保证进程不退出

很多时候当应用抛出异常后,进程退出了,就比较难排查问题。可以先改下main函数,把异常catch住:

  1.    public static void main(String[] args) throws IOException {

  2.        try {

  3.            SpringApplication.run(DemoNoSuchMethodErrorApplication.class, args);

  4.        } catch (Throwable e) {

  5.            e.printStackTrace();

  6.        }

  7.        // block

  8.        System.in.read();

  9.    }

Demo启动之后,抛出的异常是:

  1. java.lang.NoSuchMethodError: org.springframework.core.annotation.AnnotationAwareOrderComparator.sort(Ljava/util/List;)V

  2.    at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:394)

  3.    at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:383)

  4.    at org.springframework.boot.SpringApplication.initialize(SpringApplication.java:249)

  5.    at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:225)

  6.    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)

  7.    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)

  8.    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下面:

  1. ./as.sh

然后选择 com.example.demoNoSuchMethodError.DemoNoSuchMethodErrorApplication进程。

再执行sc命令来查找类:

  1. $ sc -d org.springframework.core.annotation.AnnotationAwareOrderComparator

  2. class-info        org.springframework.core.annotation.AnnotationAwareOrderComparator

  3. code-source       /Users/hengyunabc/.m2/repository/org/springframework/spring/2.5.6.SEC03/spring-2.5.6.SEC03.jar

  4. name              org.springframework.core.annotation.AnnotationAwareOrderComparator

  5. isInterface       false

  6. isAnnotation      false

  7. isEnum            false

  8. isAnonymousClass  false

  9. isArray           false

  10. isLocalClass      false

  11. isMemberClass     false

  12. isPrimitive       false

  13. isSynthetic       false

  14. simple-name       AnnotationAwareOrderComparator

  15. modifier          public

  16. annotation

  17. interfaces

  18. super-class       +-org.springframework.core.OrderComparator

  19.                     +-java.lang.Object

  20. class-loader      +-sun.misc.Launcher$AppClassLoader@5c647e05

  21.                     +-sun.misc.Launcher$ExtClassLoader@689e3d07

  22. classLoaderHash   5c647e05

  23. Affect(row-cnt:1) cost in 41 ms.

可以看到 AnnotationAwareOrderComparator是从 spring-2.5.6.SEC03.jar里加载的。

使用jad查看反编绎的源代码

下面使用jad命令来查看 AnnotationAwareOrderComparator的源代码

  1. $ jad org.springframework.core.annotation.AnnotationAwareOrderComparator

  2. ClassLoader:

  3. +-sun.misc.Launcher$AppClassLoader@5c647e05

  4.  +-sun.misc.Launcher$ExtClassLoader@689e3d07

  5. Location:

  6. /Users/hengyunabc/.m2/repository/org/springframework/spring/2.5.6.SEC03/spring-2.5.6.SEC03.jar

  7. /*

  8. * Decompiled with CFR 0_132.

  9. */

  10. package org.springframework.core.annotation;

  11. import java.lang.annotation.Annotation;

  12. import org.springframework.core.OrderComparator;

  13. import org.springframework.core.Ordered;

  14. import org.springframework.core.annotation.Order;

  15. public class AnnotationAwareOrderComparator

  16. extends OrderComparator {

  17.    protected int getOrder(Object obj) {

  18.        Order order;

  19.        if (obj instanceof Ordered) {

  20.            return ((Ordered)obj).getOrder();

  21.        }

  22.        if (obj != null && (order = obj.getClass().getAnnotation(Order.class)) != null) {

  23.            return order.value();

  24.        }

  25.        return Integer.MAX_VALUE;

  26.    }

  27. }

  28. 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来查找类,反编绎源码,确认问题

链接

  • Alibaba开源Java诊断利器: https://alibaba.github.io/arthas


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存