坊間傳聞java web開發人員寫了那麼多代碼,可是其實一半代碼都在處理NPE。老是在加班,卻大部分時間都在處理包衝突,類加載不了的bug。這些問題老是讓新老程序員都很抓狂,有不少的工具能夠輔助咱們解決這些問題(maven helper插件,arthas等)可是有沒有一些原則能夠遵循,在源頭上避免這些問題的發生呢。java
常常遇到的問題有 ClassNotFoundException
經過Class.forName()
或者loadClass()
方法加載類時,當classpath中又找不到這個類,就會拋這個錯誤。 這個錯誤通常比較好排查,編譯程序時就拋出來了。而後引入對應的jar包,或者刷新classpath就能夠解決linux
NoClassDefFoundError
類在編譯的時候存在,可是運行的時候不存在。程序員
NoSuchMethodError
找不到對應的方法,運行時纔會拋錯,這個錯誤在平常開發常常遇到,線上諸多bug都是來源於此。 發生的緣由就是多個包依賴了不同版本的另一個包,好比A,B都依賴了C包,A依賴C1,B依賴C2,工程中加載了C1,可是C1中某個類缺乏了C2版本的這個類的某個方法,這時候運行時,B依賴的C2方法被調用到了,就會報這個錯。web
既然這些問題這麼頭疼,且難以排查,還容易形成線上故障,那平時在開發過程當中如何避免這些問題。windows
重中之中就是作好二方包的管理,第三方包都是公開發布出來的,相對仍是比較靠譜的,更多的是二方包的問題。二方包發佈的頻率比較高,開發人員的水平又良莠不齊,是須要嚴格把控管理的。jvm
線上禁止snapshot包 snapshot包是萬惡之源,內容隨時會被人修改,因此線上環境,是絕對不能容許snapshot包存在,不然就是一顆定時炸彈。maven
向下兼容 版本號是3位: 主版本號.次版本號.修訂號 作了不兼容的更新要升級主版本號。在二方包管理時,儘可能不要接口層面的方法,重命名POJO類字段等不兼容的改動,由於二方包的發佈頻次高,版本比較多,維護的代價比較高。不少包發佈了幾年,仍是0.xx.xx的版本。有不兼容的改動,好比須要搭配版本時候,維護的成本都會讓人奔潰。工具
儘可能少的依賴 發佈出來的二方包儘可能少的依賴,二次依賴。對於發佈出去的包當心檢查,不要引入沒必要要的依賴。 好比有些業務repo,須要發佈rpc-client給其餘服務。對外的client與內部代碼經過不一樣module管理,那麼這時候就不要共用一份parent pom.xml。進行版本管理,由於內部工程使用的和外部不同。 不一樣領域的client也能夠拆分出來,單獨進行jar包版本管理。測試
changelog 發佈出來的版本必需要有changelog,作了什麼改動。必須依賴什麼版本的二方包也須要寫清楚。spa
優雅"copy"開源包 對於外部開源包,有些須要包裝一下在公司裏面用。切記作好如下兩點
上面說完了發佈包的原則,那麼使用包的原則呢。
優先按照依賴管理元素中指定的版本聲明進行仲裁
若無版本聲明,則按照「短路徑優先」的原則(Maven2.0)進行仲裁,即選擇依賴樹中路徑最短的版本
若路徑長度一致,則按照「第一聲明優先」的原則進行仲裁,即選擇POM中最早聲明的版本
<dependencyManagement>
來管理,這樣這些包的版本就不會被你無心間引入的某個二方包版本給覆蓋掉。常見的基礎包有中間件的包,日誌,util,序列化等包。case 1: 那是我剛來公司的時候,第一個功能上線就翻跟頭了,本地windows環境,測試linux環境都經過測試了。可是上預發的時候出了問題。排查了通宵也沒搞定,差點發布延期。最後問題根源就是「開源包」亂使用的緣由。項目中依賴了公司改造的某個mongo client
jar包,將類copy過來了,使用了相同的package,可是以不一樣的jar deploy。我來了之後,在這個工程中使用了開源的mongo client
,而後中招了。
case2: A包是一個業務基礎包,非公共基礎包。而後B,C業務依賴A。A包有些設計不合理,一個新來的大刀闊斧的各類重構了,升了一個版本,發佈了一個release包出去,完美。而後其餘業務方就炸了。由於B使用了新版本,C沒有使用新版本。一個工程中引用了B,C包後,包衝突,就會發生運行時錯誤,NoSuchMethodError
或者NoClassDefFoundError
。這時候業務方既不能升A包的版本,也不能降A的版本,可不就炸了嗎。