1. 程式人生 > >【轉】JVM載入class檔案的原理機制

【轉】JVM載入class檔案的原理機制

JVM載入class檔案的原理機制 收藏
1.Java中的所有類,必須被裝載到jvm中才能執行,這個裝載工作是由jvm中的類裝載器完成的,
類裝載器所做的工作實質是把類檔案從硬碟讀取到記憶體中

2.java中的類大致分為三種:
1.系統類
2.擴充套件類
3.由程式設計師自定義的類

3.類裝載方式,有兩種
1.隱式裝載, 程式在執行過程中當碰到通過new 等方式生成物件時,隱式呼叫類裝載器載入對應的類到jvm中,
2.顯式裝載, 通過class.forname()等方法,顯式載入需要的類
隱式載入與顯式載入的區別:
兩者本質是一樣?,


4.類載入的動態性體現
一個應用程式總是由n多個類組成,Java程式啟動時,並不是一次把所有的類全部載入後再
執行,它總是先把保證程式執行的基礎類一次性載入到jvm中,其它類等到jvm用到的時候再載入,這樣的好處是節省了記憶體的開銷,因為java最早就是為嵌入式系統而設計的,記憶體寶貴,這是一種可以理解的機制,而用到時再載入這也是java動態性的一種體現

5.java類裝載器
Java中的類裝載器實質上也是類,功能是把類載入jvm中,值得注意的是jvm的類裝載器並不是一個,而是三個,層次結構如下:
Bootstrap Loader - 負責載入系統類
|
- - ExtClassLoader - 負責載入擴充套件類
|
- - AppClassLoader - 負責載入應用類
為什麼要有三個類載入器,一方面是分工,各自負責各自的區塊,另一方面為了實現委託模型,下面會談到該模型

6. 類載入器之間是如何協調工作的
前面說了,java中有三個類載入器,問題就來了,碰到一個類需要載入時,它們之間是如何協調工作的,即java是如何區分一個類該由哪個類載入器來完成呢。
在這裡java採用了委託模型機制,這個機制簡單來講,就是“類裝載器有載入類的需求時,會先請示其Parent使用其搜尋路徑幫忙載入,如果Parent 找不到,那麼才由自己依照自己的搜尋路徑搜尋類”,注意喔,這句話具有遞迴性
下面舉一個例子來說明,為了更好的理解,先弄清楚幾行程式碼:
Public class Test{
Public static void main(String[] arg){
ClassLoader c = Test.class.getClassLoader(); //獲取Test類的類載入器
System.out.println(c);
ClassLoader c1 = c.getParent(); //獲取c這個類載入器的父類載入器
System.out.println(c1);
ClassLoader c2 = c1.getParent();//獲取c1這個類載入器的父類載入器
System.out.println(c2);
}
}
把以上程式碼存到d:\my 資料夾下,直接編譯,然後在dos模式下執行
D:\my\java Test
。。。AppClassLoader。。。
。。。ExtClassLoader。。。
Null

D:\my

注: 。。。表示省略了內容
可以看出Test是由AppClassLoader載入器載入的
AppClassLoader的Parent 載入器是 ExtClassLoader

但是ExtClassLoader的Parent為 null 是怎麼回事呵,朋友們留意的話,前面有提到Bootstrap Loader是用C++語言寫的,依java的觀點來看,邏輯上並不存在Bootstrap Loader的類實體,所以在java程式程式碼裡試圖打印出其內容時,我們就會看到輸出為null
【注:以下內容大部分引用java深度歷險】
弄明白了上面的示例,接下來直接進入類裝載的委託模型例項,寫兩個檔案,如下:
檔案:Test1.java
Public class Test1{
Public static void main(String[] arg){
System.out.println(Test1.class.getClassLoader());
Test2 t2 = new Test2();
T2.print();
}
}

檔案: Test2.java
Public class Test2{
Public void prin(){
System.out.println(this.getClass().getClassLoader());
}
}

這兩個類的作用就是打印出載入它們的類裝載器是誰, 將這兩個檔案儲存到d:\my目錄下,編譯後,我們在複製兩份,分別置於 <JRE所在目錄>\classes下(注意,剛開始我們的系統下沒有此目錄,需自己建立) 與 <JRE所在目錄>\lib\ext\classes下(同樣注意,開始我們的系統下也沒此目錄,手工建立), 然後切換到d:\my目錄下開始測試,

測試一:
<JRE所在目錄>\classes下
Test1.class
Test2.class

<JRE所在目錄>\lib\ext\classes下
Test1.class
Test2.class

D:\my下
Test1.class
Test2.class


dos下輸入執行命令,結果如下:
D:\my>java Test1
Null
Null

D:\my>

從輸出結果我們可以看出,當AppClassLoader要載入Test1.class時,先請其Parent,也就是ExtClassLoader來載入,而ExtclassLoader又請求其Parent,即Bootstrap Loader來載入Test1.class. 由於 <JRE所在目錄>\Classes目錄為Bootstrap Loader的搜尋路徑之一,所以Bootstrap Loader找到了Test1.class,因此將它載入,接著在Test1.class之內有載入Test2.class的需求,由於 Test1.class是由Bootstrap Loader所載入,所以Test2.class內定是由Bootstrap Loader根據其搜尋路徑來找,因Test2.class也位於Bootstrap Loader可以找到的路徑下,所以也被載入了,最後我們看到Test1.class與Test2.class都是由Bootstrap Loader(null)載入。


測試二:
<JRE所在目錄>\classes下
Test1.class

<JRE所在目錄>\lib\ext\classes下
Test1.class
Test2.class

D:\my下
Test1.class
Test2.class

dos下輸入執行命令,結果如下:
D:\my>java Test1
Null
Exception in thread “main” java.lang.NoClassdefFoundError:Test2 at Test1.main。。。
D:\my>

從輸出結果我們可以看出,當AppClassLoader要載入Test1.class時,先請其Parent,也就是ExtClassLoader來載入,而ExtclassLoader又請求其Parent,即Bootstrap Loader來載入Test1.class. 由於 <JRE所在目錄>\Classes目錄為Bootstrap Loader的搜尋路徑之一,所以Bootstrap Loader找到了Test1.class,因此將它載入,接著在Test1.class之內有載入Test2.class的需求,由於 Test1.class是由Bootstrap Loader所載入,所以Test2.class內定是由Bootstrap Loader根據其搜尋路徑來找,但是因為Bootstrap Loader根本找不到Test2.class(被我們刪除了),而Bootstrap Loader又沒有Parent,所以無法載入Test2.class.最後我們看到Test1.class是由Bootstrap Loader(null)載入,而Test2.class則無法載入


測試三
<JRE所在目錄>\classes下

Test2.class

<JRE所在目錄>\lib\ext\classes下
Test1.class
Test2.class

D:\my下
Test1.class
Test2.class

dos下輸入執行命令,結果如下:
D:\my>java Test1
。。。ExtClassLoader。。。
Null

D:\my>

從輸出結果我們可以看出,當AppClassLoader要載入Test1.class時,先請其Parent,也就是ExtClassLoader來載入,而ExtclassLoader又請求其Parent,即Bootstrap Loader來載入Test1.class.但是Bootstrap Loader無法在其搜尋路徑下找到Test1.class(被我們刪掉了),所以ExtClassLoader只得自己搜尋,因此 ExtClassLoader在其搜尋路徑 <JRE所在目錄>\lib\ext\classes下找到了Test1.class,因此將它載入,接著在Test1.class之內有載入Test2.class的需求,由於Test1.class是由ExtClassLoader所載入,所以Test2.class內定是由 ExtClassLoader根據其搜尋路徑來找,但是因為ExtClassLoader有Parent,所以先由Bootstrap Loader幫忙尋找,Test2.class位於Bootstrap Loader可以找到的路徑下,所以被Bootstrap Loader載入了.最後我們看到Test1.class是由ExtClassLoader載入,而Test2.class則是由Bootstrap Loader(null)載入

瞭解了以上規則,請朋友們自行分析以下場景的執行結果

測試四:
<JRE所在目錄>\classes下


<JRE所在目錄>\lib\ext\classes下
Test1.class
Test2.class

D:\my下
Test1.class
Test2.class


測試五:
<JRE所在目錄>\classes下


<JRE所在目錄>\lib\ext\classes下
Test1.class


D:\my下
Test1.class
Test2.class


測試六:
<JRE所在目錄>\classes下


<JRE所在目錄>\lib\ext\classes下

Test2.class


D:\my下
Test1.class
Test2.class


測試七:
<JRE所在目錄>\classes下


<JRE所在目錄>\lib\ext\classes下


D:\my下
Test1.class
Test2.class


以上理解,錯漏之處請朋友們及時指出,以免怠誤大家


本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/alex197963/archive/2009/08/07/4417069.aspx

相關推薦

JVM載入class檔案原理機制

JVM載入class檔案的原理機制 收藏 1.Java中的所有類,必須被裝載到jvm中才能執行,這個裝載工作是由jvm中的類裝載器完成的, 類裝載器所做的工作實質是把類檔案從硬碟讀取到記憶體中 2.java中的類大致分為三種: 1.系統類 2.擴充套件類

JVM載入Class檔案原理機制

1.java中的所以類,必須被載入到JVM中才能執行,這個載入是由類載入器完成的,類載入器所做的工作實質上是把類檔案從硬碟讀取到記憶體中 2.java中的類大致分為三種: 1、系統類 2、擴充套件類 3、程式設計師自定義的類 3.類載入的方式,兩種 1、隱式裝載,程式在執行

JVM載入class檔案原理機制

Java語言是一種具有動態性的解釋型語言,類(class)只有被載入到JVM中後才能執行。當執行指定程式時,JVM會將編譯生成的.class檔案按照需求和一定的規則載入到記憶體中,並組織成為一個完整的Java應用程式。這個載入過程是由類載入器來完成的,具體來說,就是由Clas

JVM載入class檔案原理

原始檔:編寫Java原始檔(我們也稱之為原始碼檔案),它的副檔名為.java; 編譯:然後通過編譯器把原始檔編譯成位元組碼檔案,位元組碼副檔名為.class; 執行:最後使用直譯器來執行位元組碼檔案。 類載入的主要步驟: 當程式要使用某個類時,如果該類還未被載入到記

Java中的基礎----JVM載入class檔案原理

Java是一種解釋型語言,class檔案只有被載入到JVM中才能執行。當執行指定程式時,JVM會將編譯生成的.class檔案按一定的規則(從硬碟)載入到記憶體中(由類載入器classLoader和它的子類來完成)。 有以下兩種載入方式: 1)隱式載入: 程式使用new等方式

JAVA面試常備題、JVM載入class檔案原理機制

Java中的所有類,都需要由類載入器裝載到JVM中才能執行。類載入器本身也是一個類,而它的工作就是把class檔案從硬碟讀取到記憶體中。在寫程式的時候,我們幾乎不需要關心類的載入,因為這些都是隱式裝載的,除非我們有特殊的用法,像是反射,就需要顯式的載入所需要的類。 Ja

jvm載入class檔案原理機制分析

案例分析 A、B類中均包含靜態程式碼塊,非靜態程式碼塊以及構造器,A類是B類的父類。 public class A { static { System.out.print("A中靜態程式碼塊>>>"); }

JVM載入class檔案原理機制簡單總結

Java中的所有類,必須被裝載到jvm中才能執行,這個裝載工作是由jvm中的類裝載器完成的,類裝載器所做的工作實質是把類檔案從硬碟讀取到記憶體中 java中的類大致分為三種:     1).系統類      2).擴充套件類      3).由程式設計師自定義的類類裝載方式

JVM載入class檔案原理機制是什麼?類載入器的工作原理

Java語言是一種具有動態性的解釋型語言,類(class)只有被載入到JVM中後才能執行。當執行指定程式時,JVM會將編譯生成的.class檔案按照需求和一定的規則載入到記憶體中,並組織成為一個完整的Java應用程式。這個載入過程是由類載入器來完成的,具體來說,就是由Cla

描述一下JVM載入class檔案原理機制

JVM中類的裝載是由類載入器(ClassLoader)和它的子類來實現的,Java中的類載入器是一個重要的Java執行時系統元件,它負責在執行時查詢和裝入類檔案中的類。    由於Java的跨平臺性,經過編譯的Java源程式並不是一個可執行程式,而是一個或多個類檔案。當J

Java提高篇——JVM載入class檔案原理機制

  在面試java工程師的時候,這道題經常被問到,故需特別注意。 1、JVM 簡介   JVM 是我們Javaer 的最基本功底了,剛開始學Java 的時候,一般都是從“Hello World ”開始的,然後會寫個複雜點class ,然後再找一些開源框架,比如Spring ,Hibernate 等等,再然

描述一下JVM 載入class檔案原理機制?

JVM中類的裝載是由ClassLoader和它的子類來實現的,Java ClassLoader 是一個重要的Java執行時系統元件。它負責在執行時查詢和裝入類檔案的類。 當Java編譯器編譯好.class檔案之後,我們需要使用JVM來執行這個class檔案。那

21、描述一下JVM載入class檔案原理機制

答:JVM中類的裝載是由類載入器(ClassLoader)和它的子類來實現的,Java中的類載入器是一個重要的Java執行時系統元件,它負責在執行時查詢和裝入類檔案中的類。 由於Java的跨平臺性,經過編譯的Java源程式並不是一個可執行程式,而是一個或多個類檔案。當Ja

Java進階——JVM載入class檔案原理機制

  在面試java工程師的時候,這道題經常被問到,故需特別注意。回到頂部1、JVM 簡介  JVM 是我們Javaer 的最基本功底了,剛開始學Java 的時候,一般都是從“Hello World ”開始的,然後會寫個複雜點class ,然後再找一些開源框架,比如Spring ,Hibernate 等等,再然

消息隊列原理

精彩 調用 管理 應用程序 利用 耦合 不能 開發者 一段 發布-訂閱消息模式 一、訂閱雜誌 我們很多人都訂過雜誌,其過程很簡單。只要告訴郵局我們所要訂的雜誌名、投遞的地址,付了錢就OK。出版社定期會將出版的雜誌交給郵局,郵局會根據訂閱的列表,將雜誌送達消費者手中。這樣我

二維碼生成原理

char 方法 選擇 規則 什麽是 fff mode 進行 數字相加 原文鏈接:QR碼生成原理-QR Code(ISO 18004)編碼方式 一、什麽是QR碼 QR碼屬於矩陣式二維碼中的一個種類,由DENSO(日本電裝)公司開發,由JIS和ISO將其標準化。QR碼的樣子

Go調度器原理淺析

返回 tab thread 其中 時代 使用 hat roc 思想 goroutine是golang的一大特色,或者可以說是最大的特色吧(據我了解),這篇文章主要翻譯自Morsing的[這篇博客](http://morsmachine.dk/go-scheduler),

jvm載入class檔案機制j

1、載入類檔案      a、讀取class檔案,從jar包、war包、class檔案、jsp檔案等處都可以。           a.1、採用雙親委派機制載入類,由classLoader和其子類完成,支援自定義

JVM載入class檔案的一些理解

Java是一種動態解釋型語言,類(class)只有被載入到JVM中後才能執行。每當一個Java程式執行時,都會有一個對應的JVM例項,只有當程式執行結束後,這個JVM才會退出。JVM例項通過呼叫類的main()方法來啟動一個Java程式。當執行指定程式時,JVM將編譯生成的.class檔案按照需求和一定的規則

Thread Local的正確原理與適用場景

本文轉發自技術世界,原文連結 http://www.jasongj.com/java/threadlocal/ ThreadLocal解決什麼問題 由於 ThreadLocal 支援範型,如 ThreadLocal< StringBuilder >,為表述方便,後文用 變數