天天看點

Java中Class.forName和ClassLoader.loadClass的比較

一個類型從被加載到虛拟機記憶體中開始,到解除安裝出記憶體為止,它的整個生命周期将會經曆加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和解除安裝(Unloading)七個階段,其中驗證、準備、解析三個部分統稱為連接配接(Linking)。

  加載、驗證、準備、初始化和解除安裝這五個階段的順序是确定的,類型的加載過程必須按照這種順序按部就班地開始,而解析階段則不一定:它在某些情況下可以在初始化階段之後再開始,這是為了支援Java語言的運作時綁定特性(也稱為動态綁定或晚期綁定)。這裡說的是按部就班地“開始”,而不是按部就班地“進行”或按部就班地“完成”,強調這點是因為這些階段通常都是通常都是互相交叉混合進行的,會在一個階段執行的過程中調用、激活另一個階段。

------上面是引用《深入了解Java虛拟機》中的兩段話。

下面大緻說下各階段幹了些什麼:

加載:查找和導入類或接口的二進制資料;

驗證:檢查導入類或接口的二進制資料的正确性;

準備:給類的靜态變量配置設定并初始化存儲空間;

解析:将符号引用轉成直接引用;

初始化:激活初始化類中的所有類變量的指派動作和靜态語句塊(static{})中的語句塊(初始化階段實際就是執行類構造器

<clinit>()

方法的過程);

使用:對象執行個體化,垃圾收集,對象終結等動作;

解除安裝:在jvm中解除安裝類。

類加載過程便是加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)這五個過程。

1.Class.forName

實際調用的是Class類中下面的靜态方法:

public static Class<?> forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException{}

參數的含義:

name:所需類的完全限定名

initialize:類是否要初始化(true-類将被初始化,false-類不被初始化)

loader:指定的ClassLoader(類加載器)

2.ClassLoader.loadClass

實際調用的是ClassLoader類中下面的方法:

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{}

參數的含義:

name:類名

resolve:是否解析該類

總結:

  Class.forName方法執行之後(initialize=true–初始化完成了)已經對被加載類的靜态變量配置設定完了存儲空間; ClassLoader.loadClass方法由于解析階段可能在初始化後也可能在初始化之前,是以不一定對被加載類的靜态變量配置設定完了存儲空間。

  如果想要在加載一個類的時候初始化靜态變量等推薦用Class.forName方法。