深入理解JVM之類載入

541732025發表於2014-03-25

JVM將類載入過程分為三個步驟:裝載、連結、初始化。裝載、連結完成後,即可將二進位制位元組碼轉換為Class物件,
初始化過程不是載入類時必須觸發的,只要求在初次使用物件前執行即可,初始化主要給靜態變數賦值、呼叫()等
一,裝載(load)
JVM透過類的全限定名(com.sun.HelloWorld)及類載入器(ClassLoader例項)完成類的載入,相應地,
也是用這兩個元素來標識一個被載入了的類:類的全限定名 + ClassLoader例項ID

二,連結
對二進位制位元組碼的格式進行校驗、初始化類中的靜態變數、解析類中呼叫的介面、類。
校驗過程中,如果格式不符則丟擲VerifyError,如果碰到要引用其它介面或類,也會進行載入,如果載入過程失敗,
則會丟擲NoClassDefFoundError。
完成校驗以後,JVM初始化類中的靜態變數,並將其賦值為預設值。
最後對類中所有屬性、方法進行校驗,以確保其要呼叫的屬性、方法存在,以及具備相應的許可權(如public、private等),
如果這個階段失敗,可能會造成NoSuchMethodError、NoSuchFieldError等錯誤。

三,初始化
初始化過程即執行類中的靜態初始化程式碼、構造程式碼及靜態屬性的初始化,以下幾種情況會觸發初始化過程:
1,呼叫new
2,反射呼叫了類中的方法
3,子類呼叫了初始化
4,JVM啟動過程中指定的初始化類

四,類載入器
JVM的類載入透過ClassLoader及其子類來完成,分為Bootstrap ClassLoader、Extension ClassLoader、System ClassLoader及User-Defined ClassLoader,除了Bootstrap外,剩下3個都是有父子層級關係的。
Bootstrap,此類不是ClassLoader的子類,程式碼中無法拿到這個物件,JDK啟動時會初始化該ClassLoader,並由它載入$JAVA_HOME/jre/rt.jar中所有class的載入,這些class是java規範定義的所有介面及實現(java.lang, java.util等)
Extension載入$JAVA_HOME/jre/ext/*.jar。
System載入啟動引數中指定的Classpath中的jar,簡言之,使用者寫的class會由它載入,Sun JDK中對應的實現類為AppClassLoader
User-Defined ClassLoader是開發人員自行實現的ClassLoader,可用於載入非classpath中的jar,如從網路上下載的jar或二進位制。
之前說過,ClassLoader是有父子層級關係的,當載入class時,首先會去已載入的class中查詢,如果有,直接返回,否則判斷parentClassLoader是否存在,存在,呼叫parent . loadClass,不存在,呼叫findBootstrapClassOrNull。如果最後還是找不到,則呼叫findClass,該方法預設直接throw new ClassNotFoundException,需要ClassLoader子類自己覆蓋。
但載入時也可以不採用以上順序,可以直接在當前的ClassLoader中尋找,如Class.forName(),JVM會直接透過當前ClassLoader(也就是執行Class.forName所在類的ClassLoader,caller.getClassLoader0() native方法)載入Class。
由於JVM是採用類全限定名+ClassLoader例項來判斷是否載入了某個類,所以,如果直接從當前classLoader直接載入的話,
會造成樹上多個不同的classloader中都載入了某class(某處Class.forName,某處直接new),且這些Class的例項物件都不同。JVM會保證同一個ClassLoader例項中只能載入一次同樣名稱的Class,因此可以藉助此來實現類隔離的需求。
但也會有問題,例如ClassCastException,因此在載入類時,儘量保證從根到最下層的ClassLoader上的Class只載入一次。
當ClassLoader在整個樹中都沒找到Class物件,則丟擲ClassNotFoundException

類載入的常見異常:
1,ClassNotFoundException:ClassLoader載入類時未找到該類。
2,NoClassDefFoundError:在載入的類中引用到其它的類不存在,或者載入引用的類失敗。
3,ClassCastException:兩個物件的Class有不同的ClassLoader載入。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28912557/viewspace-1129390/,如需轉載,請註明出處,否則將追究法律責任。

相關文章