## **類加載過程**

## **類加載時機**
Java虛擬機對class文件采用的是按需加載的方式,當需要使用該類時才會將它的class文件加載到內存生成class對象。只要存在于以下幾個時機:
* 創建類的實例
* 訪問某個類或接口的靜態變量,或者對該靜態變量賦值
* 調用類的靜態方法
* 反射機制獲取類
* 初始化一個類的子類(會首先初始化子類的父類)
* JVM啟動時標明的啟動類,即文件名和類名相同的那個類? ??
## **類加載器**
JVM預定義有三種類加載器,當一個?JVM啟動的時候,Java開始使用如下三種類加載器相互配合執行:
* **啟動(Bootstrap)類加載器**
主要加載的是JVM自身需要的類(jre/lib路徑下的核心類庫)
* **擴展(Extension)類加載器**
負責加載jre/lib/ext目錄下或者由系統變量\-Djava.ext.dir指定位路徑中的類庫
* **系統(System)類加載器**
負責加載系統類路徑java -classpath或\-D java.class.path 指定路徑下的類庫,也就是我們經常用到的classpath路徑,開發者可以直接使用系統類加載器
## **類加載機制**
Java虛擬機采用的是雙親委派模式來處理類的加載。所謂的雙親委派,則是先讓父類加載器試圖加載該Class,只有在父類加載器無法加載該類時才嘗試從自己的類路徑中加載該類。通俗的講,就是某個特定的類加載器在接到加載類的請求時,首先將加載任務委托給父加載器,父類如果還存在父類,則交給他的父類,依次遞歸,如果父加載器可以完成類加載任務,就成功返回;只有父加載器無法完成此加載任務時,才自己去加載。采用這種向上遞歸的方式可以保障每個類都只被加載一次。
**各個加載器的父類關系**:
* 啟動類加載器(BootstrapLoader),由C++實現,沒有父類。
* 拓展類加載器(ExtClassLoader),由Java語言實現,父類加載器為BootstrapLoader
* 系統類加載器(AppClassLoader),由Java語言實現,父類加載器為ExtClassLoader
* 自定義類加載器,父類加載器肯定為AppClassLoader。
## **自定義類加載器**
```
public class MyClassloader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
// 讀取字節
InputStream is = this.getClass().getResourceAsStream(fileName);
byte[] bytes = new byte[is.available()];
is.read(bytes);
// 將byte字節流解析成jvm能夠識別的Class對象
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
```