java -- java.lang.NoSuchMethodError的問題

TheSnowBoy_2發表於2016-07-08

讓這個問題折騰了好長時間,最終在網上看到了一篇文章,解決了這個問題。

轉自: http://timen-zbt.iteye.com/blog/1871152

在Java專案進行增量更新的時候經常會出現java.lang.NoSuchMethodError的問題,究其原因有很多:

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

2、開發環境和執行環境的不一致

3、以上兩點都齊全,並且確實有對應的方法存在,依然報java.lang.NoSuchMethodError錯誤

。。。

 

本文章主要解決第三種問題:對應的方法存在卻依然報java.lang.NoSuchMethodError錯誤

錯誤重現:

搭建Java工程,並生成如下兩個類

TestNoSuchMethodError用於測試

 

Java程式碼  收藏程式碼
  1. package com.timen.demo;  
  2.   
  3. public class TestNoSuchMethodError {  
  4.     public static void main(String[] args) {  
  5.         Person p = new Person();  
  6.         p.setName("timen");  
  7.         p.setSuperUser(true);  
  8.         System.out.println(p.getName() + " is Super User? " + p.isSuperUser());  
  9.     }  
  10. }  
 Person
Java程式碼  收藏程式碼
  1. package com.timen.demo;  
  2.   
  3. public class Person {  
  4.     private String name;  
  5.     private boolean superUser;  
  6.       
  7.     public Person() {  
  8.     }  
  9.     public String getName() {  
  10.         return name;  
  11.     }  
  12.     public void setName(String name) {  
  13.         this.name = name;  
  14.     }  
  15.     public boolean isSuperUser() {  
  16.         return superUser;  
  17.     }  
  18.     public void setSuperUser(boolean superUser) {  
  19.         this.superUser = superUser;  
  20.     }  
  21.   
  22. }  
 注意:該類的superUser屬性為boolean原生資料型別
執行TestNoSuchMethodError,結果如下:

Python程式碼  收藏程式碼
  1. D:\MyWorkspace\sts\NoSuchMethodError\bin>java com.timen.demo.TestNoSuchMethodError  
  2. timen is Super User? true  
  3.   
  4. D:\MyWorkspace\sts\NoSuchMethodError\bin>  
將這兩個類的編譯後的Class檔案(包括包目錄)儲存到其他目錄下(相當於釋出工程到正式環境中),然後修改Person類
Java程式碼  收藏程式碼
  1. package com.timen.demo;  
  2.   
  3. public class Person {  
  4.     private String name;  
  5.     private Boolean superUser;  
  6.       
  7.       
  8.     public Person() {  
  9.     }  
  10.     public String getName() {  
  11.         return name;  
  12.     }  
  13.     public void setName(String name) {  
  14.         this.name = name;  
  15.     }  
  16.     public Boolean isSuperUser() {  
  17.         return superUser;  
  18.     }  
  19.     public void setSuperUser(Boolean superUser) {  
  20.         this.superUser = superUser;  
  21.     }  
  22.   
  23. }  
 注意:這裡將superUser屬性的型別改為Boolean(boolean的封裝型別)
然後將編譯後的Person.class拷貝到剛剛釋出的專案中替換掉剛才的Person.class檔案(注意你沒有更改TestNoSuchMethodError類,所以大多你不會想更新這個類)
問題發生了:
Python程式碼  收藏程式碼
  1. D:\temp>java com.timen.demo.TestNoSuchMethodError  
  2. Exception in thread "main" java.lang.NoSuchMethodError: com.timen.demo.Person.setSuperUser(Z)V  
  3.         at com.timen.demo.TestNoSuchMethodError.main(TestNoSuchMethodError.java:7)  
  4.   
  5. D:\temp>  
 報出java.lang.NoSuchMethodError: com.timen.demo.Person.setSuperUser(Z)錯誤。
該java.lang.NoSuchMethodError為setSuperUser(Z)對應的方法應該是setSuperUser(boolean var)
而在新的Person檔案中的setSuperUser方法的簽名為可以用javap -s Person檢視:
Python程式碼  收藏程式碼
  1. D:\temp\com\timen\demo>javap -s Person  
  2. Compiled from "Person.java"  
  3. public class com.timen.demo.Person extends java.lang.Object{  
  4. public com.timen.demo.Person();  
  5.   Signature: ()V  
  6. public java.lang.String getName();  
  7.   Signature: ()Ljava/lang/String;  
  8. public void setName(java.lang.String);  
  9.   Signature: (Ljava/lang/String;)V  
  10. public java.lang.Boolean isSuperUser();  
  11.   Signature: ()Ljava/lang/Boolean;  
  12. public void setSuperUser(java.lang.Boolean);  
  13.   Signature: (Ljava/lang/Boolean;)V  
  14. }  
  15. D:\temp\com\timen\demo>  
 這裡就查到原因了,Java在編譯的時候確定方法的簽名,而Boolean為引用型別使用Ljava/lang/Boolean;簽名,而boolean為原生資料型別,用Z作為簽名,所以兩次編譯TestNoSuchMethodError所生成的位元組碼並不相同。而我們在做手動增量更新的時候又竟然忘記,就會出現java.lang.NoSuchMethodError錯誤。


相關文章