Java AbstractMethodError 原因分析

背景

AbstractMethodError異常對於我來說還是比較不常遇見的,最近有幸遇到,並僥倖的解決了,在這裏把此種場景剖析一番,進入正題,下面是AbstractMethodError在Java的異常機制中所處的位置:

AbstractMethodError類圖

現在明確了AbstractMethodError所具有的特性:

1.它是Error的子類,Error類及其子類都是被劃分在非檢查異常之列的,就是說這些異常不能在編譯階段被檢查出來,只能在運行時纔會觸發。

2.通過API文檔裏面的解釋大致得出的結論就是說A依賴於B,但是執行的時候發現類B的定義發生了改變,這個改變是針對編譯的時候發生了改變,也就是說將類A由java文件編譯成.class文件的時候用到了類B的class文件,但是在執行的時候JVM發現真正用到的B的class文件和編譯的時候用的不是一個了。於是這個異常就被拋了出來。

至此,AbstractMethodError發生的底層原因也瞭解的差不多了,再往深層的話就是java的編譯機制,以及java代碼的執行檢查這些更靠近虛擬機的東東,那些我也沒什麼研究,暫且不表。

底層原因瞭解了,我們繼續談下平常遇到的更直觀的場景:

ClassA ->ClassB  ClassA 依賴於ClassB,通常A是我們自己開發的類,而B則是引用的第三方jar包裏面的類。我們的項目中又存在ClassB的多個版本,比如:1.0,1.2,2.0等版本,通常主版本號發生了改變的話,一般都是不兼容的。

類A

class A {
	B dependency = new BImpl();
	
	public void testMethod(){
		dependency.changedMethodInDifVersion(arg1, arg2);
	}
}
1.0版本的類B:

abstract class B {
<span style="white-space:pre">	</span>public abstract void changedMethodInDifVersion(int arg1);
}
2.0版本的ClassB:

abstract class B {
<span style="white-space:pre">	</span>public abstract void changedMethodInDifVersion(int arg1, String arg2);
}

如果在編譯的時候使用的2.0版本中的這個ClassB,然而執行的時候使用的又是1.0版本的ClassB,那麼就會拋出AbstractMethodError,這個異常拋出以後會把運行時真正找到的那個方法簽名給打印出來的,異常信息會入下:

Exception in Thread XXXXX java.lang.AbstractMehodError  package.Class.運行時實際找到的方法

這個時候在你的classpath中尋找這個類,剔除掉不需要的版本就可以了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章