問題來源java
這段時間咱們在切換某海外環境的登陸體系,遇到一個應用會話校驗有問題,排查過程以下:session
從會話邏輯trace去看,走到了tair獲取session的代碼裏,實例代碼以下:jvm
public class SessionManagerProxyImpl implements CnSessionManagerProxy {
private volatile static Map<String,SessionManager> sessionManagerMap = Maps.newHashMap();
public SessionResult get(String sessionId) { 。。。。 SessionManager cnSessionManager = sessionManagerMap.get(readLocation); 。。。。 }
}
經過greys的sc排查到SessionManager竟然沒有加載到jvm中,因而趕忙去學習了下。。。。學習
「加載」的定義spa
首先要了解下咱們上面所說的「加載」的定義是什麼:.net
jvm把描述類的數據從class文件加載到內存,並對數據進行校驗、轉換解析和初始化,最終造成能夠被虛擬機直接使用的Java類型,這就是虛擬機的加載機制code
趕忙翻了下【深刻理解jvm虛擬機】,類從被加載到jvm內存中開始,到卸載出內存爲止,它的整個生命週期包括了:加載(Loading)---> 驗證(Verification)--->準備(Preparation)--->解析(Resolution)--->初始化(Initialization)--->使用(using)--->卸載(Unloading)七個階段對象
所以,咱們上面sc到加載的類,這裏所說的「加載」是5個階段的的總和,而不是其中的「加載(Loading)」blog
加載的時機生命週期
1.遇到new、getstatic、putstatic或invokestatic這4條字節碼指令時,若是類沒有進行過初始化,則須要先觸發其初始化。生成這4條指令最多見的Java代碼場景是:使用new關鍵字實例化對象時、讀取或者設置一個類的靜態字段(被final修飾、已在編譯器把結果放入常量池的靜態字段除外)時、以及調用一個類的靜態方法的時候。
2.使用java.lang.reflect包的方法對類進行反射調用的時候,若是類沒有進行過初始化,則須要先觸發其初始化。
3.當初始化一個類的時候,若是發現其父類尚未進行過初始化,則須要觸發父類的初始化。
4.當虛擬機啓動時,用戶須要指定一個執行的主類(包含main()方法的類),虛擬機會先初始化這個類。
總結
JVM加載類是一種懶加載的模式,只有在須要某個類的時候纔會加載,只是聲明某個類的引用而不建立對象的時候是不會加載的,所以上面的SessionManager沒有加載的問題就很好解釋了
參考:
http://blog.csdn.net/u010425776/article/details/51251430
http://chenzhou123520.iteye.com/blog/1597597