讓這個問題折騰了好長時間,最終在網上看到了一篇文章,解決了這個問題。
轉自: http://timen-zbt.iteye.com/blog/1871152
在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錯誤。