From: https://blog.csdn.net/luanlouis/article/details/40043991 Step 1.根據JVM記憶體配置要求,為JVM申請特定大小的記憶體空間 JVM啟動時按照其配置要求,申請一塊記憶體,並根據JVM規範和實現將記憶體劃分為幾個區域。 所有的類的定義信 ...
From: https://blog.csdn.net/luanlouis/article/details/40043991
Step 1.根據JVM記憶體配置要求,為JVM申請特定大小的記憶體空間
JVM啟動時按照其配置要求,申請一塊記憶體,並根據JVM規範和實現將記憶體劃分為幾個區域。
所有的類的定義信息都會被載入到方法區。
Step 2. 創建一個引導類載入器實例,初步載入系統類到記憶體方法區區域中;
JVM申請好記憶體空間後,JVM會創建一個引導類載入器(Bootstrap Classloader)實例,引導類載入器是使用C++語言實現的。
引導類載入器(Bootstrap Classloader)會讀取{JRE_HOME}/lib下的jar包和配置(JVM虛擬機運行時所需的基本系統級別的類),然後將這些系統類載入到方法區內,如java.lang.String, java.lang.Object等等。
Step 3. 創建JVM 啟動器實例 Launcher,並取得類載入器ClassLoader
此時,JVM虛擬機調用已經載入在方法區的類sun.misc.Launcher
的靜態方法 getLauncher()
, 獲取 sun.misc.Launcher
實例。
sun.misc.Launcher launcher = sun.misc.Launcher.getLauncher(); //獲取Java啟動器
ClassLoader classLoader = launcher.getClassLoader(); //獲取類載入器ClassLoader用來載入class到記憶體來;
// 返回 AppClassLoader 實例,AppClassLoader將ExtClassLoader作為自己的父載入器。
sun.misc.Launcher 使用了單例模式設計,保證一個JVM虛擬機內只有一個sun.misc.Launcher實例。 在Launcher的內部,其定義了兩個類載入器(ClassLoader),分別是sun.misc.Launcher.ExtClassLoader和sun.misc.Launcher.AppClassLoader,
這兩個類載入器分別被稱為拓展類載入器(Extension ClassLoader) 和 應用類載入器(Application ClassLoader).
拓展類載入器(Extension Class Loader):
該載入器是用於載入 java 的拓展類 ,拓展類一般會放在 {JRE_HOME}/lib/ext/ 目錄下,用來提供除了系統類之外的額外功能。拓展類載入器是是整個JVM載入器的Java代碼可以訪問到的類載入器的最頂端,即是超級父載入器,拓展類載入器是沒有父類載入器的。
應用類載入器(Applocatoin Class Loader):
該類載入器是用於載入用戶代碼,是用戶代碼的入口。我經常執行指令 java xxx.x.xxx.x.x.XClass , 實際上,JVM就是使用的AppClassLoader載入 xxx.x.xxx.x.x.XClass 類的。應用類載入器將拓展類載入器當成自己的父類載入器,當其嘗試載入類的時候,首先嘗試讓其父載入器-拓展類載入器載入;如果拓展類載入器載入成功,則直接返回載入結果Class<T> instance,載入失敗,則會詢問是否引導類載入器已經載入了該類;只有沒有載入的時候,應用類載入器才會嘗試自己載入。由於xxx.x.xxx.x.x.XClass是整個用戶代碼的入口,在Java虛擬機規範中,稱其為 初始類(Initial Class).
## 雙親委派模型類載入: --------
Step 4. 使用類載入器ClassLoader載入Main類
通過 launcher.getClassLoader()方法返回AppClassLoader實例,接著就是AppClassLoader載入我們寫的 xxx.xxx.TestMain類的時候了。
當AppClassLoader要載入 xxx.xxx.TestMain.class時,會去查看該類的定義,class文件中有一個叫常量池(Constant Pool)的結構體來存儲該class的常量信息。常量池中有CONSTANT_CLASS_INFO類型的常量,表示該class中聲明瞭要用到那些類。.xxx.xxx.TestMain類要想正常工作,首先要能夠保證這些其內部聲明的類載入成功。所以AppClassLoader要先將這些類載入到記憶體中。
JVM方法區的類信息區是按照類載入器進行劃分的,每個類載入器會維護自己載入類信息;
某個類載入器在載入相應的類時,會相應地在JVM記憶體堆(Heap)中創建一個對應的Class<T>,用來表示訪問該類信息的入口
Step 5. 使用Main類的main方法作為程式入口運行程式
Step 6. 方法執行完畢,JVM銷毀,釋放記憶體