Java虛擬機器 類載入的過程

來源:互聯網
上載者:User

轉載請標明出處:http://blog.csdn.net/xuefeng0707/article/details/9132339


類載入的全過程分為五個階段:載入、驗證、準備、解析、初始化。


1. 載入

這個階段可分為三段:

(1)載入二進位位元組流

根據類的全限定名(包名+類名),擷取此類的二進位位元組流。

虛擬機器規範沒有指定二進位位元組流從哪裡讀取,可以是class檔案,可以是jar,也可以由動態代理在運行時產生,等等,只要是符合規範的位元組流即可,由類載入器來決定位元組流的來源。

(2)產生方法區的資料結構

根據前一步讀取到的位元組,在方法區建立運行時資料結構。

(3)建立Class執行個體

在Java堆中建立java.lang.Class的執行個體,作為程式碼訪問類型資料的外部介面。

2. 驗證

這個階段驗證讀取到的二進位位元組流是否符合虛擬機器規範中Class檔案的儲存格式,如果不符合,拋出java.lang.VerifyError異常或其子類的異常。

這個階段分為四段:

(1)檔案格式驗證

驗證位元組流是否符合Class檔案格式的規範。

有以下這些驗證點:

  • 是否已魔數0xCAFEBABE開頭。
  • 主次版本號碼是否能被當前虛擬機器處理。
  • 常量池的常量中是否有不被支援的類型。
  • 常量池裡的項是否執行不存在的常量或不符合類型的常量。
  • 。。。。。。
註:這裡的常量池不是指運行時虛擬機器記憶體中的常量池,而是class檔案的一部分。  (http://www.blogjava.net/DLevin/archive/2011/09/05/358033.html)經過檔案格式驗證後,位元組流進入虛擬機器記憶體的方法區進行儲存,具體的資料結構實現由虛擬機器決定。後面的驗證都是基於此處的方法區中的資料結構進行的。(2)中繼資料驗證進行語義分析,以確保class檔案描述的類資訊符合Java語言的規範。也就是編譯能通過。有以下這些驗證點:
  • 是否 有父類(除java.lang.Object外,所有類都應有父類)。
  • 是否繼承了final類。
  • 如果不是抽象類別,是否實現了所有需要實現的方法。
  • 。。。。。。
(3)位元組碼驗證進行資料流和控制流程分析,對類的方法體進行校正,確保類的方法在運行時不作出危害虛擬機器安全的行為。
  • 確保 跳轉指令不會跳到方法體以外的指令上。
  • 確保類型轉換是合法有效。
  • 。。。。。。
(4)符號引用驗證在“解析”階段,把常量池內的符號引用轉化為直接飲用的時候,要先驗證符號引用。
  • 通過全限定名,是否能找到相應的類
  • 是否能找到指定類中的指定的欄位或方法
  • 類、欄位或方法的可訪問性是否合適。
  • 。。。。。。

如果無法通過符號引用驗證,將拋出一個java.lang.IncompatibleClassChangeError的子類。
3. 準備在方法區,為static field分配記憶體,並設定其初始值。這裡設定的初始值,是Java虛擬機器定義的對應於各種類型的預設值。例如:
private static int value=123;

經過準備階段後,value的值為0,而不是123。賦值是在初始化階段的<clinit>()完成的。

但是,對於static final field,在此階段是直接賦值的。例如:
private static final int value=123;

經過準備階段後,value的值為123。

Java虛擬機器中各種類型的預設初始值。

資料類型 預設初始值
int 0
long 0L
short (short)0
char '\u0000'
byte (byte)0
boolean false
float 0.0f
double 0.0d
reference null
4. 解析

把類檔案的常量池部分的符號引用轉化為運行時常量池的直接引用。

  • 解析類或介面

                   


  • 解析欄位


  • 解析類方法


  • 解析介面方法


5. 初始化

執行<clinit>()。

  • <clinit>()中包含了一個類中所有類變數的賦值動作和靜態塊(寫在static{ }裡)的語句。執行順序按在源檔案中出現的順序。
  • <clinit>()不需要調用父類的<clinit>(),這是由虛擬機器來確保完成的。
  • 介面的<clinit>()中只包含介面中欄位的賦值操作,父介面的<clinit>()不需要在子介面或實作類別的<clinit>()之前執行,只有在真正引用到了父介面中定義的欄位時,才會執行父介面的<clinit>()。
  • <clinit>()是安全執行緒的。如果多個線程同時去初始化一個類,只有一個線程會去執行初始化,其他的線程都會阻塞。





















聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.