Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

利用Arthas排查Spring Boot应用NoSuchMethodError #160

Closed
hengyunabc opened this issue Sep 25, 2018 · 13 comments
Closed

利用Arthas排查Spring Boot应用NoSuchMethodError #160

hengyunabc opened this issue Sep 25, 2018 · 13 comments

Comments

@hengyunabc
Copy link
Collaborator

前言

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

链接

@wangmeng1314
Copy link

给力

@yooocen
Copy link

yooocen commented Oct 3, 2018

给力

1 similar comment
@dong4j
Copy link

dong4j commented Oct 8, 2018

给力

@fangsh2015
Copy link

牛逼

@hzdavid
Copy link

hzdavid commented Oct 12, 2018

上面的issue是系统已经出现了NoSuchMethodError,如果想知道系统里还有哪些类,可能会造成NoSuchMethodError呢? 能否在maven打包时就能发现呢?

借这个issue机会,推广一下自己的插件。 https://github.com/hzdavid/findConflicts
使用步骤相当简单:

git clone https://github.com/hzdavid/findConflicts
cd findConflicts
mvn install

然后在自己工程的pom.xml中,比如上面的Demo: https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-NoSuchMethodError
pom.xml里配置插件
<plugin> <groupId>findconflicts</groupId> <artifactId>fc-maven-plugin</artifactId> <version>1.0.0-SNAPSHOT</version> <executions> <execution> <phase>package</phase> <goals><goal>go</goal></goals> </execution> </executions> <configuration> <versionCheckConfig>${basedir}/versionCheck.pb</versionCheckConfig> </configuration> </plugin>

然后mvn fc:go -Dshow.class.conflicts=true

类冲突,jar冲突,日志冲突一览无余.

刚才试过,AnnotationAwareOrderComparator 这个冲突类,这个插件就找到了。

希望楼主不要删除这个comment啊,偶可是arthas忠实fans。

have fun!

@MoPei
Copy link

MoPei commented Oct 23, 2018

这种问题一般都应该是包冲突造成的,一般的包用idea 的插件Maven Helper就能解决,阿尔萨斯应该在线上或回归环境定位诡异的问题才能体现她的价值吧

@wenlaizhou
Copy link

上面的issue是系统已经出现了NoSuchMethodError,如果想知道系统里还有哪些类,可能会造成NoSuchMethodError呢? 能否在maven打包时就能发现呢?

借这个issue机会,推广一下自己的插件。 https://github.com/hzdavid/findConflicts
使用步骤相当简单:

git clone https://github.com/hzdavid/findConflicts
cd findConflicts
mvn install

然后在自己工程的pom.xml中,比如上面的Demo: https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-NoSuchMethodError
pom.xml里配置插件
<plugin> <groupId>findconflicts</groupId> <artifactId>fc-maven-plugin</artifactId> <version>1.0.0-SNAPSHOT</version> <executions> <execution> <phase>package</phase> <goals><goal>go</goal></goals> </execution> </executions> <configuration> <versionCheckConfig>${basedir}/versionCheck.pb</versionCheckConfig> </configuration> </plugin>

然后mvn fc:go -Dshow.class.conflicts=true

类冲突,jar冲突,日志冲突一览无余.

刚才试过,AnnotationAwareOrderComparator 这个冲突类,这个插件就找到了。

希望楼主不要删除这个comment啊,偶可是arthas忠实fans。

have fun!

请教一下哈, dependence tree 能不能解决这个问题呢?

@hzdavid
Copy link

hzdavid commented Oct 30, 2018

上面的issue是系统已经出现了NoSuchMethodError,如果想知道系统里还有哪些类,可能会造成NoSuchMethodError呢? 能否在maven打包时就能发现呢?
借这个issue机会,推广一下自己的插件。 https://github.com/hzdavid/findConflicts
使用步骤相当简单:
git clone https://github.com/hzdavid/findConflicts
cd findConflicts
mvn install
然后在自己工程的pom.xml中,比如上面的Demo: https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-NoSuchMethodError
pom.xml里配置插件
<plugin> <groupId>findconflicts</groupId> <artifactId>fc-maven-plugin</artifactId> <version>1.0.0-SNAPSHOT</version> <executions> <execution> <phase>package</phase> <goals><goal>go</goal></goals> </execution> </executions> <configuration> <versionCheckConfig>${basedir}/versionCheck.pb</versionCheckConfig> </configuration> </plugin>
然后mvn fc:go -Dshow.class.conflicts=true
类冲突,jar冲突,日志冲突一览无余.
刚才试过,AnnotationAwareOrderComparator 这个冲突类,这个插件就找到了。
希望楼主不要删除这个comment啊,偶可是arthas忠实fans。
have fun!

请教一下哈, dependence tree 能不能解决这个问题呢?

dependence tree解决不了,dependence tree只能显示最终的jar依赖结果,这些jar有没有冲突,它并不知道。

@linkingli
Copy link

点赞

@52learn
Copy link

52learn commented Jan 7, 2019

请问下我现在通过Idea运行com.example.demoNoSuchMethodError.DemoNoSuchMethodErrorApplication#main 没有报错啊, 没有java.lang.NoSuchMethodError:异常的 怎么回事?

@einverne
Copy link

maven enforcer 可以在引入依赖时就去发现冲突,而不是非要等到线上出现问题。

@924936307
Copy link

牛气!

@weiguojian
Copy link

上面的issue是系统已经出现了NoSuchMethodError,如果想知道系统里还有哪些类,可能会造成NoSuchMethodError呢? 能否在maven打包时就能发现呢?

借这个issue机会,推广一下自己的插件。 https://github.com/hzdavid/findConflicts
使用步骤相当简单:

git clone https://github.com/hzdavid/findConflicts
cd findConflicts
mvn install

然后在自己工程的pom.xml中,比如上面的Demo: https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-NoSuchMethodError
pom.xml里配置插件
<plugin> <groupId>findconflicts</groupId> <artifactId>fc-maven-plugin</artifactId> <version>1.0.0-SNAPSHOT</version> <executions> <execution> <phase>package</phase> <goals><goal>go</goal></goals> </execution> </executions> <configuration> <versionCheckConfig>${basedir}/versionCheck.pb</versionCheckConfig> </configuration> </plugin>

然后mvn fc:go -Dshow.class.conflicts=true

类冲突,jar冲突,日志冲突一览无余.

刚才试过,AnnotationAwareOrderComparator 这个冲突类,这个插件就找到了。

希望楼主不要删除这个comment啊,偶可是arthas忠实fans。

have fun!

在我的场景下 java.lang.NoSuchMethodError: org.springframework.core.annotation.AnnotationAwareOrderComparator.sort(Ljava/util/List;)V, 使用你的插件找不到具体冲突包啊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests