当程序试图调用不存在的类方法时,抛出java.lang.NoSuchMethodError
异常。该方法可以是静态的,也可以是实例方法。
java.lang.NoSuchMethodError示例
大多数情况下,java.lang.NoSuchMethodError
由编译器捕获,但有时它可能在运行时发生。如果在运行时发生此错误,那么唯一的原因可能是类结构的更改使其不兼容。
让我们尝试在运行时引发此错误。所以有两个类:Data
和Temp
,如下所示。
public class Data {
public void foo() {
System.out.println("foo");
}
public void bar() {
System.out.println("bar");
}
}
文件:Temp.java
public class Temp {
public static void main(String[] args) {
Data d = new Data();
d.foo();
d.bar();
}
}
两个程序看起来都没有问题,下面通过命令行编译和运行它们。请注意,稍后将更改Data
类时,不使用Eclipse或任何其他IDE来避免编译时检测到此错误。
D:/worsk/java> javac Data.java
D:/worsk/java> javac Temp.java
D:/worsk/java> java Temp
foo
bar
下面将更改Data
类的定义,如下所示。
public class Data {
public void foo() {
System.out.println("foo");
}
// public void bar() {
// System.out.println("bar");
// }
}
请注意,上面已删除bar()
方法。现在将只编译Data
类,不编译主类。
D:/worsk/java> javac Data.java
D:/worsk/java> java Temp
foo
Exception in thread "main" java.lang.NoSuchMethodError: Data.bar()V
at Temp.main(Temp.java:7)
D:/worsk/java>
正如所看到的,已经抛出了一个java.lang.NoSuchMethodError
异常,因为Data
类与Temp
类不兼容。如果编译Data
类,就会遇到编译时错误,如下所示。
D:/worsk/java> javac Temp.java
Temp.java:7: error: cannot find symbol
d.bar();
^
symbol: method bar()
location: variable d of type Data
1 error
D:/worsk/java>
Tomcat中的java.lang.NoSuchMethodError
大多数情况下,在一些具有许多依赖项的应用程序中看到java.lang.NoSuchMethodError
异常。这有两个主要原因 -
编译时使用的Jar版本与运行时不同。例如,应用程序中可能有MySQL jar,其版本与Tomcat lib文件夹中的版本不同。由于Java Classloader首先查看tomcat lib文件夹jar,因此如果在加载的类中找不到任何方法,则有可能出现
java.lang.NoSuchMethodError
异常。由于同一类名冲突。例如,应用程序正在使用一些第三方jar,它具有与相同的完全限定类名。因此,如果
classloader
从其他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.yiibai.spring.controller.HomeController from file:/Users/maxsu/Downloads/apache-tomcat-8.5.16/webapps/spring-mvc-example/WEB-INF/classes/]