java.lang.NoSuchMethodError示例
当程序尝试调用不存在的类方法时,将引发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/]