前言
在生產環境,我們為了降低發版風險,一般都只做增量發布,不做全量發布.
除非項目只有一到兩人開發,對時間線和代碼脈絡結構一清二楚,才可全量發布.
然而增量發布也是有一定隱藏陷阱在里面的,以下就是筆者的項目組在增量迭代過程中一起遇上到陷阱
陷阱1 : 匿名內部類
如果修改的java源碼中,有匿名內部類,那么最終在WEB-INF/classes/.......package....../Person.java 下面會生Person$XXX.class的匿名內部類,
但是我們在提交svn時,一般不涉及classes/下面的class文件的提交.
於是帶來的問題是svn僅僅發現變更了源文件Person.java ,等到通過svn的記錄都增量打jar包提交生產環境的時候. 經常會把Person$XXX.class匿名內部類給遺漏了.
導致上生產一般會報"類找不到"的異常.
解決方法: 參考我的另一篇文章 windows cmd命令 批處理bat 導增量jar包【原】
陷阱2 : 方法重載
和前一個問題有點相似,但不完全一樣.
假如有以下兩個java文件.
Test.java
package test; import test.Person; public class Test { public static void main(String[] args) { Person person = new Person(); person.setId(18); person.setName("bobo"); System.out.println(person.getId()); } }
Person.java
package test; public class Person { int id = 0; String name = ""; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
現在把eclipse里面的Person.java的 id 屬性從int 改成 Integer
package test; public class Person { Integer id = 0; String name = ""; public int getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
那么從源碼Test.java的角度出發來講,肉眼是看不出變化, 沒錯,源碼還是源碼. svn也不會發現變化.
但是! 其實 setId(int id) 和setId(Integer id) 這根本不是同一個方法, 這叫方法重載,在Person.java中本來就是可以並存的, 然而這個方法重載很特別, 因為int 和 Integer 是基本類型和對象類型互通的, 所以調用setId(18) 不管是用setId(int id) 還是 setId(Integer id)都可以 , 於是eclipse也不會報錯, 其java文件還真是不需要修改的, 這就演變了成一個隱藏的陷阱, class早就發生變化了(eclipse 自動編譯).
雖然java源碼沒變化,但所有調用到 Person對象的setId(Integer id)方法的class全發生變化了.所以這個時候增量發包的時候可能會很嚴重了,發生產后,隱藏的class(比如Test.class) 全沒提交, 報一堆的java.lang.NoSuchMethodError異常. 這是筆者對Person變化前后用bccompare工具對Test.class文件作的二進制對比
於此同時double 和 Double , float 和 Float 也都要特別小心方法重載時的其它調用類的底層class是否有變化.
解決方案: 無 ! 只能向項目組強調 以 防患於未然 , 或者用 jenkin 等完善的自動化工具做全量發布。