深入SpringBoot:利用Arthas排查NoSuchMethodError

橫雲斷嶺發表於2018-09-27

前言

有時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來查詢類,反編繹原始碼,確認問題

連結


相關文章