當j**a編譯器編譯好.class檔案之後,我們需要使用jvm來執行這個class檔案。那麼最開始的工作就是要把位元組碼從磁碟輸入到記憶體中,這個過程我們叫做【載入】。載入完成之後,我們就可以進行一系列的執行前準備工作了,比如: 為類靜態變數開闢空間,將常量池存放在方法區記憶體中並實現常量池位址解析,初始化類靜態變數等等。這篇文章我們要好好談談jvm是如何載入class檔案的?
1、jvm載入類的過程
使用者自定義類裝載器經常依賴其他類裝載器——至少依賴於虛擬機器啟動時建立的啟動類裝載器—來幫助它實現一些類裝載請求:.在版本1.2前,非啟動類裝載器 必須顯式地求助於其他類裝載器,類裝載器可以請求另乙個使用者自定義的類裝載器來裝載乙個類,這個請求是通過對被請求的使用者自定義類裝載器呼叫 loadclass()來實現的。除此以外,類裝載器也可以通過呼叫findsystemclass()來請求啟動類裝載器來裝載類,這是類 classloader中的乙個靜態方法。
在版本1.2中,類裝載器請求另乙個類裝載器來裝載型別的過程被形式化,稱為雙親委派模式 。
從版本1.2開始、除啟動類裝載器以外的每乙個類裝載器,都有乙個「雙親」類裝載器 ,在某個特定的類裝載器試圖以常用方式裝載型別以前,它會先預設地將這個任務「委派」給它的雙親——清求它的雙親來裝載這個型別。這個雙親再依次請求它自 己的雙親來裝載這個型別。這個委派的過程一直向上繼續,直到達到啟動類裝載器,通常啟動類裝載器是委派鏈中的最後乙個類裝載器。如果乙個類裝載器的雙親類 裝載器有能力來裝載這個型別。則這個類裝載器返回這個型別。否則,這個類裝載器試圖自己來裝載這個類。
當j**a虛擬機器開始執行時,在應用程式開始啟動以前,它至少建立乙個使用者自定義裝載器,也可能建立多個.所有這些裝載器被連線在乙個parent-child的委託鏈中,在這個鏈的頂端是啟動類裝載器。
例如:假設你寫了乙個應用程式,在虛擬機器上執行它.虛擬機器在啟動時例項化了兩個使用者自定義類裝載器:乙個"擴充套件類裝載器",乙個"類路徑類裝載器".這些類裝載器和啟動類裝載器一起聯入乙個parent-child委託鏈中,如下圖所示.
上圖所示類路徑類裝載器的parent是擴充套件類裝載器, 擴充套件類裝載器的parent是啟動類裝載器.在圖2中,類路徑類裝載器就被例項為系統類裝載器.假設你的程式例項化它的網路類裝載器,它就指明了系統類裝載器作為它的parent.
下面的例程說明了類裝載器的父子關係.
j**a**
package test;
import j**a.net.url;
import j**a.net.urlclassloader;
public class classloadertest
classloader cl = null;
if (obj != null && !(obj instanceof classloader)) else if (obj != null)
count++;
string parent = "";
for (int i = 0; i
if (cl != null) else
}
public static void main(string args)
}
4、乙個經典的例項說明
我們看看下面的**:
j**a**
package j**a.lang;
public class string
} j**a.lang.nosuchmethoderror: main
exception in thread "main"
這是為什麼? 我們的string類不是明明有main方法嗎?
啟動類載入器bootstraploader只能載入j**a_home\jre\lib中的class類(即j2se api),問題是標準api中確實有乙個j**a.lang.string(注意,這個類和我們自定義的類是完全兩個類)。bootstraploader以為找到了這個類,毫不猶豫的載入了j2se api中的j**a.lang.string。
最後出現上面的載入錯誤(注意不是異常,是錯誤,jvm退出),因為api中的string類是沒有main方法的。
結論:我們當然可以自定義乙個和api完全一樣的類,但是由於雙親委託模型,使得我們不可能載入上我們自定義的這樣乙個類。所以j2se規範中希望我們自定義的包有自己唯一的特色(網路網域名稱)。還有一點,這種載入器原理使得jvm更加安全的執行程式,因為黑客很難隨意的替代掉api中的**了。
JVM載入class檔案的原理機制?
jvm中類的裝載是由類載入器 classloader 和它的子類來實現的,j a中的類載入器是乙個重要的j a執行時系統元件,它負責在執行時查詢和裝入類檔案中的類。由於j a的跨平台性,經過編譯的j a源程式並不是乙個可執行程式,而是乙個或多個類檔案。當j a程式需要使用某個類時,jvm會確保這個類...
jvm原理 簡單的程式載入分析
package com.bzu.csh 類載入器載入.class檔案 初始化static宣告,並不賦值 呼叫類 static宣告賦值由上到下 程式開始執行,首先執行main方法,執行main方法第一條語句,呼叫singleton類的靜態方法,這裡呼叫singleton類的靜態方法就是主動使用sing...
jvm 類的載入機制與原理
jvm j a virtual machine 可以被拆分為好幾個部分,最開始的類載入器,執行引擎,本地介面 執行時資料區域。本章節主要針對類的載入機制進行說明 目前基本都知道,類在被執行時,需要經過堆類的載入,鏈結 驗證 準備 解析 和初始化的階段以及後面的 階段。那麼類是怎麼被載入的呢?類載入器...