`
timen_zbt
  • 浏览: 76331 次
社区版块
存档分类
最新评论

java.lang.NoSuchMethodError 调试和解决方法

阅读更多

 

 

在Java项目进行增量更新的时候经常会出现java.lang.NoSuchMethodError的问题,究其原因有很多:

1、在引包是引用了不匹配的包版本

2、开发环境和运行环境的不一致

3、以上两点都齐全,并且确实有对应的方法存在,依然报java.lang.NoSuchMethodError错误

。。。

 

本文章主要解决第三种问题:对应的方法存在却依然报java.lang.NoSuchMethodError错误

错误重现:

搭建Java工程,并生成如下两个类

TestNoSuchMethodError用于测试

 

package com.timen.demo;

public class TestNoSuchMethodError {
	public static void main(String[] args) {
		Person p = new Person();
		p.setName("timen");
		p.setSuperUser(true);
		System.out.println(p.getName() + " is Super User? " + p.isSuperUser());
	}
}
 Person
package com.timen.demo;

public class Person {
	private String name;
	private boolean superUser;
	
	public Person() {
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public boolean isSuperUser() {
		return superUser;
	}
	public void setSuperUser(boolean superUser) {
		this.superUser = superUser;
	}

}
 注意:该类的superUser属性为boolean原生数据类型
执行TestNoSuchMethodError,结果如下:

D:\MyWorkspace\sts\NoSuchMethodError\bin>java com.timen.demo.TestNoSuchMethodError
timen is Super User? true

D:\MyWorkspace\sts\NoSuchMethodError\bin>
将这两个类的编译后的Class文件(包括包目录)保存到其他目录下(相当于发布工程到正式环境中),然后修改Person类
package com.timen.demo;

public class Person {
	private String name;
	private Boolean superUser;
	
	
	public Person() {
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Boolean isSuperUser() {
		return superUser;
	}
	public void setSuperUser(Boolean superUser) {
		this.superUser = superUser;
	}

}
 注意:这里将superUser属性的类型改为Boolean(boolean的封装类型)
然后将编译后的Person.class拷贝到刚刚发布的项目中替换掉刚才的Person.class文件(注意你没有更改TestNoSuchMethodError类,所以大多你不会想更新这个类)
问题发生了:
D:\temp>java com.timen.demo.TestNoSuchMethodError
Exception in thread "main" java.lang.NoSuchMethodError: com.timen.demo.Person.setSuperUser(Z)V
        at com.timen.demo.TestNoSuchMethodError.main(TestNoSuchMethodError.java:7)

D:\temp>
 报出java.lang.NoSuchMethodError: com.timen.demo.Person.setSuperUser(Z)错误。
该java.lang.NoSuchMethodError为setSuperUser(Z)对应的方法应该是setSuperUser(boolean var)
而在新的Person文件中的setSuperUser方法的签名为可以用javap -s Person查看:
D:\temp\com\timen\demo>javap -s Person
Compiled from "Person.java"
public class com.timen.demo.Person extends java.lang.Object{
public com.timen.demo.Person();
  Signature: ()V
public java.lang.String getName();
  Signature: ()Ljava/lang/String;
public void setName(java.lang.String);
  Signature: (Ljava/lang/String;)V
public java.lang.Boolean isSuperUser();
  Signature: ()Ljava/lang/Boolean;
public void setSuperUser(java.lang.Boolean);
  Signature: (Ljava/lang/Boolean;)V
}
D:\temp\com\timen\demo>
 这里就查到原因了,Java在编译的时候确定方法的签名,而Boolean为引用类型使用Ljava/lang/Boolean;签名,而boolean为原生数据类型,用Z作为签名,所以两次编译TestNoSuchMethodError所生成的字节码并不相同。而我们在做手动增量更新的时候又竟然忘记,就会出现java.lang.NoSuchMethodError错误。
 
 
 
分享到:
评论
3 楼 木杉是天才 2016-11-02  
感谢楼主,这个思路非常好,帮助我解决了问题
2 楼 xialia8 2016-08-15  
感谢楼主,根据你的修改了方法签名这个思路解决了一个问题
1 楼 w111222j 2015-10-26  
谢谢。。我们的项目也一直报这个错,终于找到原因 了。因为是引用的包没有重新编译出问题了。

相关推荐

Global site tag (gtag.js) - Google Analytics