聊聊線上崩潰

前言

大改版上線,這一週累的跟孫子似的,幾乎天天2,3點睡覺,最要命的是,出現了一些及其詭異的bug,有一些現在仍然沒有找到任何原有,並且我估計也不可能找到原因了,下面簡單說一說其中遇到的一個問題。
這篇文章也是開篇吧,用來記錄以後工作中遇到的一些奇葩的,比較容易拿出來探討的一些問題。

問題彙總

noSuchMethodError

復現

復現場景如下:A模塊調用B模塊的x方法,x方法返回值爲w1,打包A模塊爲aar,然後,修改B模塊的x方法返回值爲w2,然後打包B模塊,然後聯合打包出包,就出現了這個問題。

猜測原因

這個肯定涉及到打包部分的代碼,樓主目前也不是相當瞭解,所以,只能猜測,打包某個模塊,肯定是打包成aar(.class文件),而不是打包成.dex文件。
所以下面我們說說,.class文件有什麼特殊的,爲什麼會造成這種問題。
下面我們來模擬一下這種情況,看看.class文件裏面究竟有什麼。
模擬代碼

\\TestNoSuchMethodError.java文件
public class TestNoSuchMethodError {
    public void tat(B b) {
        b.get();
    }
}
\\B.java文件
public class B {
    public String get() {
        return "";
    }
}

上面就是模擬情況,我們先使用

javac -d .\ *.java

來把這兩個文件編譯成.class文件,再使用

java -p  .\TestNoSuchMethodError.class

來查看調用的方法。
下面是截圖
在這裏插入圖片描述
注意最後的tat那一行
在這裏插入圖片描述
看到invokevirtual#7 應該就能明白了,#7在第一張圖中。這裏其實指定了方法描述符。注意,java虛擬機層面,是使用java方法名和方法簽名來唯一確認一個方法調用。這裏經常和java方法描述符搞混,方法描述符和方法簽名是不一樣的

方法簽名是由方法的名稱和參數類型構成。
方法簽名的存在是爲了在Java語法層面上保證開發者能夠正確的命名方法、重載方法。

方法描述符是由方法的參數類型以及返回類型所構成。
JVM在判定重寫時,看的是方法描述符。

注意,一個是java層面的,一個是jvm層面的。也可以理解爲,jvm是允許,相同方法名,相同方法參數,但是不同返回值存在的,也就是說,jvm的重載判斷方法和java的重載判斷方法不一樣。
真相大白。

總結

這隻會是一個系列的開篇,後續我會把相關遇到的知識點性質的bug陸續都總結到這個裏面來,歡迎大家一起探討提問。

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