深究一個靜態代碼塊不被執行問題
問題現象:
- spring環境中的bean 的靜態代碼塊會被自動執行
- 工具類中的靜態代碼塊不被自動執行,工具類第一次被調用時靜態代碼塊執行
- 通過子類調用繼承的父類的方法,子類靜態代碼塊不被執行
複習ClassLoad
Java類加載 會初始化的情況有且僅有以下五種:(也稱爲主動引用)
1.遇到new(用new實例對象),getStatic(讀取一個靜態字段),putstatic(設置一個靜態字段),invokeStatic(調用一個類的靜態方法)這四條指令字節碼命令時
2.使用Java.lang.reflect包的方法對類進行反射調用時,如果此時類沒有進行init,會先init。
3.當初始化一個類時,如果其父類沒有進行初始化,先初始化父類
4.jvm啓動時,用戶需要指定一個執行的主類(包含main的類)虛擬機會先執行這個類
5.當使用JDK1.7的動態語言支持的時候,當java.lang.invoke.MethodHandler實例後的結果是REF-getStatic/REF_putstatic/REF_invokeStatic的句柄,並且這些句柄對應的類沒初始化的話應該首先初始
問題分析
-
工具類中的靜態代碼塊不被自動執行
項目啓動時工具類不滿足Java類加載條件,因此未初始化,在第一次調用時,滿足Java類加載條件,ClassLoad同時執行靜態代碼塊
-
通過子類調用繼承的父類的方法,子類靜態代碼塊不被執行
對應於Java類加載 第一條,invokeStatic的對象是父類,雖然是子類引用了父類方法,但是代碼的歸屬權上歸屬於父類,因此子類靜態代碼塊不執行(拓展子類引用父類靜態變量同理)
-
拓展問是不是在項目啓動時類一定會被加載到內存
答案時否定的,使用時纔會加載。因此對性能要求較高情況需考慮啓動時全量加載。