Java 類型的加載和鏈接都是在運行期間,這樣可能會有性能開銷,可是卻能提供動態擴展的語言特性。
git
解析可能在初始化以後進行數組
vm規範規定了四個點必須對類進行初始化:網絡
- 遇到new ,getstatic,putstatic, invokestatic幾個指令的時候。也就是new, 使用設置靜態變量,引用靜態方法的時候 訪問靜態變量只會形成當前類的初始化,不會初始化子類,這裏還要注意,對於被final修飾、在編譯器已經放入常量池的靜態屬性不會觸發初始化。 new 數組是不會初始化類的
- reflect包的方法對類進行反射調用的時候
- 初始化時要先初始化父類
- 虛擬機啓動時要指定主類,主類會先初始化
過程
加載
1. 根據全名獲取二進制字節流 沒有指明流的來與,因而能夠是jar包,網絡,動態代理在運行時生成
2. 在方法區生成該類的運行時數據結構
3. 在堆上建立Class對象,做爲對方法區數據訪問入口
驗證
要求知足字節碼格式規範等
準備
爲類變量分配內存並設定初始值的階段, 不涉及實例變量,都在方法區進行。
解析
將常量池內的符號引用替換爲直接引用的過程。
符號引用就是字面量, 沒有指向實際的內存,只是表示知道這個類有這個引用,但具體引用到哪裏還不知道
直接引用, 是鏈接了實際目標的符號引用
初始化
執行類client()方法的過程, 由編譯器收集的類變量賦值動做和static方法塊合併成的。
虛擬保證client是順序執行的,所以要注意若是static預發快中有死循環會形成阻塞
類加載器
- 工做流程: 收到加載請求後,交給父加載器去完成, 父完不成才會嘗試本身完成。 以下是個過程 Class c = findClass(name); if(c == null){ c = parent.loadClass(name); } if(c == null){ // 父不行了,本身來 c = findClass(name) } return c;
- 破壞雙親委派
- JNDI 雙親委派解決不了基礎類須要調用用戶代碼的狀況 JNDI服務由啓動加載器加載,可是其用到的接口類卻由各個廠商提供,啓動加載器就會找不到,引入了線程上下文加載器,須要使用Thread.setContextClassLoader()進行設置。JNDI就是用了這個加載器
- OSGI, 每一個boundler一個類加載器,import的類委託給export的類加載器去加載。