增量部署class文件引起的血案

背景

項目中經過遠程調用服務框架調用了許多其它的服務,其中有一個服務wx/subscribe/contract/CircleService 須要升級,其升級不是版本上的升級,而是整個服務從新取了一個名字,使用的也是全新的jar包wuxian/social/contract/SocialService,可是調用的方法沒有改變,所以在升級時,只是在調用服務service類中修改了調用地址,和調用返回實體(由CircleService改成SocialService),該service中返回該調用實體使用的是static方法.修改完畢事後本地運行一切正常,因而將修改service的class文件以及對應的jar包上到沙箱環境,並將沙箱環境中原來的CircleService jar包刪除,而後重啓,可是報錯了.代碼修改以下:
java

private static volatile CircleService subCircleService = null;
subCircleService = ProxyFactory.create(CircleService .class,"tcp://circle/CircleServiceImpl" );
public static CircleService getSubCircleService() {
        return subCircleService;
    }

修改成服務器

private static volatile SocialService subCircleService = null;
subCircleService = ProxyFactory.create(SocialService.class,"tcp://social/SocialServiceImpl" );
public static SocialService getSubCircleService() {
        return subCircleService;
    }

其它地方的調用都是用類名+方法名(SCFService.getSubCircleService())的方式訪問,故此,在修改時只改動了這個文件,其它文件都沒有修改,增量上線的時候也只上線該文件便可.框架

報錯現象

重啓服務器的時候沒法啓動服務,一直報以下錯誤
圖片描述tcp

錯誤內容爲找不到wx/subscribe/contract/CircleService這個jar包提供的方法,很奇怪爲何會提示這個錯誤,剛開始懷疑是上線的class文件有問題,沙箱上部署class文件沒有成功,仍是原來的文件,因此又部署了一次,可是仍是報一樣的錯誤.spa

解決過程

將部署到沙箱上的文件下載下來,進行反編譯,看引用中是否存在CircleService相關的jar包應用,結果反編譯後,發現報錯的文件中都沒有CircleService相關的jar包引用,因而在cmd窗口中使用javap編譯class文件code

javap -v xx.class > D:/result.txt

使用該命令後,在result.txt中的常量池中,驚人的發現竟然還有引用CircleService相關jar包的行
圖片描述blog

故此解開了爲什麼代碼中爲什麼會報上述錯誤的問題,因而將雖然代碼沒有改動,可是從新編譯事後的class文件上到沙箱,重啓,結果果真沒有報錯了,因而上線.可是上線事後才發現,其它類在訪問時候纔會調用該方法的類依舊會報上述錯誤,因而從新檢查了一遍全部引用過上述修改過的方法的類,將從新編譯事後的文件都上線,才解決了報錯的問題,這就是增量上線class文件引起的一塊兒血案.圖片

思考

咱們觀察在在上述報錯中,報錯內容爲NoSuchMethodError,而不是ClassNotFound,這是爲何呢?在其它代碼引用上述修改的方法時,都是經過SCFService.getSubCircleService()的方式調用,而沒有寫返回類,在調用上述方法時,老的class文件常量池中,getSubCircleService()返回的是CircleService方法,而新上線的SCFService中該方法的返回值已經修改成SocialService,故此會先報NoSuchMethodError錯誤.
這種錯誤相似於咱們在常量類中定義ci

public static final CONST = 100;

後,要修改常量CONST值爲1000後,只增量上線了該常量class文件,而其它引用該常量的類的文件都更新上線所引起的CONST依舊爲100的問題.部署

相關文章
相關標籤/搜索