目的:將class文件加載到內存
1:JVM基本結構
類加載器、執行引擎、運行時數據區(堆、棧,方法區)、本地接口
Class Files -> ClassLoader -> 運行時數據區 -> 執行引擎、本地庫接口 -> 本地方法庫
2:類的裝卸
加載、鏈接(驗證、準備、解析)、初始化、使用、卸載
3:Class 二進制文件,保存類的定義或者結構, 放到堆中
4:初始化:執行類的「構造器」,爲類的靜態變量賦予正確的初始值
5:構造器
static 變量
static 代碼塊
誰在前誰先執行
6:構造方法
實例化對象
7:構造器與構造方法
構造器:構造的是類,爲類的靜態變量、靜態代碼塊賦值
構造方法:構造的是實例對象
8:類加載器雙親委派模型
默認的加載器都有一個父類加載器,(除了啓動加載器,不是繼承關係,是包含與組合的關係)
classLoader試圖加載類的時候,必須將加載的任務委託給父類加載器,若是父類加載器沒有加載到該類的時候,反過來委託給發起者,
本身自己加載,若是尚未,則報錯classNotFound 異常。能避免類的重複加載
某個特定的類加載器在接到加載類的請求時,首先將加載任務委託給父類加載器,依次遞歸,若是父類加載器能夠完成類加載任務,
就成功返回;只有父類加載器沒法完成此加載任務時,才本身去加載。
使用雙親委派模型的好處在於Java類隨着它的類加載器一塊兒具有了一種帶有優先級的層次關係。例如類java.lang.Object,
它存在在rt.jar中,不管哪個類加載器要加載這個類,最終都是委派給處於模型最頂端的Bootstrap ClassLoader進行加載,
所以Object類在程序的各類類加載器環境中都是同一個類。相反,若是沒有雙親委派模型而是由各個類加載器自行加載的話,
若是用戶編寫了一個java.lang.Object的同名類並放在ClassPath中,那系統中將會出現多個不一樣的Object類,程序將混亂。
所以,若是開發者嘗試編寫一個與rt.jar類庫中重名的Java類,能夠正常編譯,可是永遠沒法被加載運行。
https://blog.csdn.net/u014138443/article/details/90581981
9:JDK自帶加載器
Bootstrap ClassLoader
JVM要啓動java程序,須要本身先啓動,JVM也是一個程序 C++寫的
最頂層的加載類,主要加載核心類庫,%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等。
另外須要注意的是能夠經過啓動jvm時指定-Xbootclasspath和路徑來改變Bootstrap ClassLoader的加載目錄。
好比java -Xbootclasspath/a:path被指定的文件追加到默認的bootstrap路徑中。咱們能夠打開個人電腦,在上面的目錄下查看,
看看這些jar包是否是存在於這個目錄。
Extention ClassLoader
extends ClassLoader 擴展的類加載器,加載目錄%JRE_HOME%\lib\ext目錄下的jar包和class文件。還能夠加載-D java.ext.dirs選項指定的目錄。
Appclass Loader
extends ClassLoader 也稱爲SystemAppClass 加載當前應用的classpath的全部類。 src下面的就是classPath
10:自定義加載器
xxx extends ClassLoader
徹底自定義路徑
public class Demo {
//################### 1:begin 構造器加載 #########################################
public int tem = 1; //非靜態變量,初始化時不會被賦值
public static int staticTem = 1; //類構造時默認初始值爲0,走到這裏,後賦值成1
static {
staticTem = 2; //賦值爲2
System.out.println("static " + staticTem);
}
//################### 1:end 構造器加載 #########################################
public static void main(String[] args) {
//################### 1:test 構造器加載 #########################################
staticTem = 3;
System.out.println("main " + staticTem);
System.out.println(new Demo().tem);
//################### 2:test 類加載器加載 #########################################
ClassLoader classLoader = Demo.class.getClassLoader();
while (classLoader != null) {
System.out.println("classLoader==" + classLoader);
classLoader = classLoader.getParent();
}
//結果
//classLoader==sun.misc.Launcher$AppClassLoader@18b4aac2
//classLoader==sun.misc.Launcher$ExtClassLoader@5197848c
System.out.println("classLoader==" + classLoader); //null 爲何不是Bootstrap? Bootstrap是C++寫的,null表明就是Bootstrap
}
/*
classLoad 加載
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name); 爲null時從Bootstrap加載 } */}