java.lang.NoSuchMethodError示例

时间:2020-02-23 14:36:40  来源:igfitidea点击:

当程序尝试调用不存在的类方法时,将引发java.lang.NoSuchMethodError。
该方法可以是静态的,也可以是实例方法。

java.lang.NoSuchMethodError

在大多数情况下,都是通过编译器捕获" java.lang.NoSuchMethodError",但有时可能会在运行时发生。
如果在运行时发生此错误,则唯一的原因可能是类结构的更改导致其不兼容。

让我们尝试在运行时引发此错误。
因此,我们有两个类"数据"和"温度",如下所示。

public class Data {

	public void foo() {
		System.out.println("foo");
	}
	
	public void bar() {
 		System.out.println("bar");
 	}
}
public class Temp {

	public static void main(String[] args) {

		Data d = new Data();
		d.foo();
		d.bar();

	}

}

这两个程序看起来都不错,让我们编译并通过命令行运行它们。
请注意,稍后我将更改Data类时,我没有使用Eclipse或者任何其他IDE来避免对该错误进行编译时检测。

hyman:Downloads hyman$javac Data.java 
hyman:Downloads hyman$javac Temp.java 
hyman:Downloads hyman$java Temp
foo
bar
hyman:Downloads hyman$

因此,程序可以很好地执行,让我们继续进行操作,如下所示更改Data类的定义。

public class Data {

	public void foo() {
		System.out.println("foo");
	}
	
	//public void bar() {
//		System.out.println("bar");
//	}
}

注意,我删除了bar()方法。
现在我们只需要编译Data类,而不编译主类。

hyman:Downloads hyman$javac Data.java 
hyman:Downloads hyman$java Temp
foo
Exception in thread "main" java.lang.NoSuchMethodError: Data.bar()V
	at Temp.main(Temp.java:7)
hyman:Downloads hyman$

如您所见,因为Data类与Temp类不兼容,所以我们得到了java.lang.NoSuchMethodError。
如果我们尝试编译Data类,则会出现编译时错误,如下所示。

hyman:Downloads hyman$javac Temp.java 
Temp.java:7: error: cannot find symbol
		d.bar();
		 ^
symbol:   method bar()
location: variable d of type Data
1 error
hyman:Downloads hyman$

Tomcat中的java.lang.NoSuchMethodError

大多数时候,您会在某些依赖关系很多的应用程序中看到" java.lang.NoSuchMethodError"。
这有两个主要原因。

  • 编译时使用的Jar版本与运行时不同。
    例如,您的应用程序中的MySQL jar的版本可能与Tomcat lib文件夹中的版本不同。
    由于tomcat lib文件夹jar是Java Classloader首先查看的,因此如果在加载的类中未找到任何方法,则有可能出现java.lang.NoSuchMethodError`。

  • 由于类名相同而发生冲突。
    例如,您的应用程序正在使用某些第三方jar,该第三方jar与您的完全相同的类名。
    因此,如果类加载器从其他jar加载类,则在运行时将获得java.lang.NoSuchMethodError

调试java.lang.NoSuchMethodError

您可以使用Java运行时选项-verbose:class获取有关用于加载类的jar的信息。
您可以在tomcat catalina.sh或者setenv.sh中设置此配置,如下所示。

JAVA_OPTS="$JAVA_OPTS -verbose:class"

然后,您将看到类似以下的日志,这对弄清加载类时使用的实际jar以及运行时java.lang.NoSuchMethodError的原因非常有帮助。

[Opened /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Object from /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.io.Serializable from /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded com.theitroad.spring.controller.HomeController from file:/Users/hyman/Downloads/apache-tomcat-8.5.16/webapps/spring-mvc-example/WEB-INF/classes/]