乙方的煩惱---如何在乙方升級的情況下甲方不用升級?


故事背景

自古以來,做買賣、特別是供大於求情況下,市場游戲總會出現乙方有求於甲方的現象。

 

 

 在現在的市場經濟機制下,甲方和乙方的地位更難平等,小王是深有體會。小王是一家軟件外包公司的員工,他們為一家國企提供軟件服務,最近小王比較煩,因需求變更,甲方大爺軟件中引用的一個jar中的常量發生了變化,他們更新了jar包,但甲方只同意將新jar包替換掉舊的jar包,導致系統出現執行異常!甲方限令必須盡快找到問題並解決掉!

為了防止公司信息泄露,我們模擬一下這個場景:

public class BinaryCompatibilityTest {

    public static void main(String[] args) {
        System.out.println(DefineConstants.FIRST + " " +
                DefineConstants.SECOND + " " +
                DefineConstants.THIRD);
                }
}

其中DefineConstants來自甲方對乙方的引用:

import com.test.constants.Words;

public class DefineConstants {
    private DefineConstants() { }; // Uninstantiable
    public static final String FIRST = Words.FIRST;
    public static final String SECOND = Words.SECOND;
    public static final String THIRD = Words.THIRD;

}

其中,Words是引用的公用jar包

 

 

 類實現如下:

package com.test.constants;

public class Words {
    private Words() {
    }; // Uninstantiable

    public static final String FIRST = "the";
    public static final String SECOND = null;
    public static final String THIRD = "set";
}

 

原先打印結果為

the null set

 

現在乙方小王修改了jar包后,代碼變成了

package com.test.constants;

public class Words {
    private Words() {
    }; // Uninstantiable

    public static final String FIRST = "physics";
    public static final String SECOND = "chemistry";
    public static final String THIRD = "biology";
}

他將重新打包后的jar包傳給甲方,讓甲方在tomcat上替換原來的jar包,結果運行后打印的結果卻為:

the chemistry set

小王百思不得其解。

 

 

 反復確認了jar包是否正確,都是最新的jar包。

萬般無奈之下只好請出被辭退的中老年技術大神"老司機",並答應老司機1w/d的辛苦費。

 

 老司機了解了情況后,就找到了原因,通過jd-gui反編譯了代碼給小王看:

 

 替換了jar包后,DefineConstants並沒有被重新編譯,導致FIRST和THIRD的結果沒有發生改變,

但因SECOND本身為null,在編譯期常量表達式(compile-time constant expression)[JLS15.28]的精確定義中找到。它的定義太長了,就不在這里寫出來了,但是理解這

個程序的行為的關鍵是null 不是一個編譯期常量表達式。運行時就會執行新的結果:chemistry

解決辦法是

1. 需要重新編譯DefineConstants后,替換到新的class

2.重新編譯整個項目的打包文件,提供新的包文件替換舊的打包文件

第一個方案

   優點: 線上改動小,影響小,速度快

   缺點:只能解決當前問題,如果項目中還有別的地方引用這個變量,將還會出錯。

第二個方案

   優點:從根本上解決問題

   缺點:線上影響稍微大一些。

 

小王入司剛兩年,是個勤奮好學的家伙,項目搞定后請老司機吃飯喝酒,趁老司機酒醉,趁機問解決這個問題的訣竅,老司機喝迷糊后道出了本質:

原來java考慮到升級的問題,有二進制兼容性規范,。。。。。。。。。

因老司機喝的有點多,描述的不是很清楚,小王只記住了在jsl規范了有明確的描述:jsl 13章,https://docs.oracle.com/javase/specs/jls/se12/html/index.html

 

 

 

 

參考資料:

【1】http://blog.sina.com.cn/s/blog_4c408e27010009ae.html

【2】java解惑

【3】https://docs.oracle.com/javase/specs/jls/se12/html/index.html

【4】https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.28


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM