從排查一個登陸問題看jvm類加載機制

問題來源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)七個階段對象

  • 其中加載包括5個階段:加載(Loading)---> 驗證(Verification)--->準備(Preparation)--->解析(Resolution)--->初始化(Initialization)
  • 在加載的過程當中的3個環節稱爲鏈接(Linking):驗證(Verification)--->準備(Preparation)--->解析(Resolution)
  • 因此加載的過程是:加載(Loading)---> 鏈接(Linking)--->初始化(Initialization)

所以,咱們上面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

相關文章
相關標籤/搜索