V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hengyunabc
V2EX  ›  Java

Arthas 实践--排查 Spring Boot 应用 NoSuchMethodError

  •  
  •   hengyunabc ·
    hengyunabc · 2018-10-23 19:18:39 +08:00 · 1496 次点击
    这是一个创建于 2250 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

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

    链接

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2830 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 08:38 · PVG 16:38 · LAX 00:38 · JFK 03:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.