JVM-類載入機制

来源:http://www.cnblogs.com/lrh-xl/archive/2016/04/04/5352317.html
-Advertisement-
Play Games

虛擬機類載入機制 虛擬機把描述的類的數據從class文件載入到記憶體後,並對數據進行校驗,轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類載入機制。 虛擬機類載入機制 虛擬機把描述的類的數據從class文件載入到記憶體後,並對數據進行校驗,轉換解析和初始化,最終形成可以被虛 ...


虛擬機類載入機制 

  虛擬機把描述的類的數據從class文件載入到記憶體後,並對數據進行校驗,轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類載入機制。

 類載入的時機

   類被載入到虛擬機記憶體開始,到卸載出記憶體為止。它的整個生命周期包括:類載入(Loading),驗證(Verification),準備(Preparation),解析(Resolution),初始化(Initialization),使用(Using)和卸載(Unloading)7個階段。其中驗證,準備,解析3個部分統稱為連接(Linking)。

  虛擬機規範嚴格規定了有且僅有5種情況必須立即對類進行“初始化”:

  1. 遇到new , getstatic , putstatic 或involvestatic這4條位元組碼指令時,如果類沒有進行過初始化,則需要先觸發其初始化。
  2. 使用java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有進行過初始化,則需要先觸發其初始化。
  3. 當初始化一個類的時候,如果發現其父類還沒有進行過初始化,則需要先觸發其父類的初始化。
  4. 當虛擬機啟動時,用戶需要指定一個要執行的主類(包含main方法的類),虛擬機會先初始化這個類。
  5. 當使用JDK1.7的動態語言支持時,如果java.lang.invoke.MethodHeadle實例,最後的解析結果REF_getstatic , REF_putstatic , REF_invokestatic的方法句柄,並且這個方法句柄所對應的類沒有進行過初始化,則需要先觸發其初始化。

 類載入的過程

  一、載入

  (1)在載入階段,虛擬機需要完成以下3件事:

  1. 通過一個類的全限定名來獲取定義此類的二進位位元組流
  2. 將這個位元組流所代表的靜態存儲結構結構轉化為方法區的運行時數據結構
  3. 在記憶體中生成一個代表這個類的java.lang.class對象,作為方法區這個類的各種數據的訪問入口

  (2)數組類本身不通過類載入器創建,他是由Java虛擬機直接創建的。

    一個數組類創建過程遵循以下規則:

  1. 如果數組的組件類型(Component Type , 指的是數組去掉一個維度的類型)是引用類型,那就遞歸採用上面介紹的載入過程去載入這個組件類型,數組將在載入該數組組件類型的類載入器的類名稱空間上唄標識。
  2. 如果數組的組件類型不是7引用類型,Java虛擬機將會把數組標記為與引導類載入器關聯。
  3. 數組類的可見性與它的組件類型的可見性一致,如果組件類型不是引用類型,需要數組類的可見性將 預設為public

 

  二、驗證

  驗證是連接階段的第一步,這一階段的目的是為了確保class文件的位元組流包含的信息符合當前虛擬機的要求,並且不會危害虛擬機本省的安全。

  驗證階段大致上會完成以下4個階段的檢驗動作:文件格式驗證、元數據驗證、位元組碼驗證、符號引用驗證

  (1 ) 文件格式驗證

  1. 第一階段要驗證位元組流是否符合class文件格式的規範,並且能被當前版本的虛擬機處理。
  2. 中油通過了這個階段的驗證後,位元組流才會進入記憶體的方法區中進行存儲,所以後面的3個驗證階段全部是基於方法區的存儲結構進行的,不會直接操作位元組碼。

 (2 ) 元數據驗證

  1. 第二階段是對位元組碼描述的信息進行語義分析,以確保其描述的信息符合Java語言規範的要求。
  2. 第二階段的主要目的是對類的元數據信息進行語義化驗,保證不存在不符合Java語言規範的元數據信息

  (3 ) 位元組碼驗證

  1. 督三階段是整個驗證過程中最複雜的一個階段,主要目的是通過數據流和控制流分析,確定程式語義是合法的,符合邏輯的。這個階段將對類的方法體進行校驗分析。保證被校驗類的方法運行時不會做出危害虛擬機安全的時間。
  2. 例如:保證任意時刻操作數棧的數據類型與指令代碼序列都能配合工作。保證跳轉到方法體以外的位元組碼指令上。

  (4 ) 符號引用驗證

  1. 最後一個驗證階段的檢驗發生在虛擬機將符號引用轉化為直接引用的時候,這個轉化動作將在連接階段的第三階段——解析階段中發生。符號引用驗證可以看做是對類自身以外的信息進行匹配性校驗。
  2. 例如:符號引用中通過字元串描述中的全限定名是否能找到對應的類。在特定類中是否存在符合方法的欄位描述符以及簡單名稱所描述的方法和欄位
  3. 符號引用驗證的目的是確定解析動作能正常執行,如果無法通過符號引用驗證,那麼將會拋出java.lang.IncompatibleClassChangeError異常的子類

  

 三、準備

  準備階段是正式為類變數 分配記憶體並設置類變數初始值的階段,這些變數所使用的記憶體將在方法區中進行分配。

 

  四、解析

  (1)解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程。

  1. 符號引用(symbolic Reference):符號引用逸一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用 時能無歧義地定位到引用目標即可。符號引用與虛擬機實現的記憶體佈局無關,引用的目標並不一定已經載入到記憶體中。各種虛擬機實現的記憶體佈局可以各不相同,但是它們能接受的符號引用必須是一致的,因為符號引用的字面量形式明確定義在Java虛擬機規範中的class文件格式中。
  2. 直接引用(Direct Reference):直接引用可以是直接指向目標的指針。相對偏移量或是一個能間接定位到目標的句柄。直接引用是和虛擬機實現的記憶體佈局相關的,同一個符號引用在不同的虛擬機實例上翻譯出來的直接引用一般不會相同,如果有了直接引用那引用的目標必定已經在記憶體中存在。

  (2)虛擬機規範中並未規定解析階段發生的具體時間,只要求了執行anewarray,checkcast,getfield,getstatic,instanceof,invokedynamic,invokeinterface,invokespecial,invokestatic,invokevirtual,ldc,ldc_w,multianewarray,new,putField和putstatic這16個用於操作符號引用的位元組碼指令之前,先過它們所使用的符號引用進行解析。

  (3)解析動作主要針對類或介面,欄位,類方法,介面方法,方法類型,方法句柄和調用點限定符7類符號引用進行。

  (4)類或介面的解析

    虛擬機完成整個解析的過程需要以下3個步驟

    1)如果c不是一個數組類型,那虛擬機將會把代表N的全限定名傳遞給D的類載入器去載入這個類C。在載入過程中,由於元數據驗證,位元組碼驗證的需要,又可能觸發其他相關的類的載入動作。

    2)如果C是一個數組類型,並且數組的元素類型為對象,那將會按以上的規則載入數組類型。如果N的描述符如前面所假設的形式,需要載入元素的類型,接著由虛擬機生成一個代表此數組維度和元素的數組對象。

    3)如果上面的步驟沒有出現任何異常,那麼C在虛擬機中實際上已經成為一個有效的類或介面了,但在解析完成之後還要進行符號引用驗證,確認D是否是具備對C的訪問許可權。

  (5)欄位解析

  (6)類方法解析

  (7)介面方法解析

 

  五、初始化

  1. 類初始化階段是類載入過程的最後一步
  2. 在準備階段,變數已經賦過一次系統要過的初始值,而在初始化階段,則根據程式員制定的主觀去初始化變數和其他資源,或者可以從另外一個角度來表達:初始化階段是執行類構造器<cninit>()方法的過程。
  3. <clinit>()方法是由編譯器自動收集類中的所有類變數的賦值動作和靜態語句塊(static{}塊)中的語句合併產生的,編譯器收集的順序是由語句在源文件中出現的順序所決定的,靜態語句塊只能訪問到定義在靜態語句塊之前的變數,定義在它之後的變數,在前面的靜態語句塊可以賦值,但是不能訪問。
  4. <clinit>()方法與類的構造函數不同,它不需要顯式地調用父類構造器,虛擬機會保證在子類的<clinit>()方法執行之前,父類的<clinit>()方法已經執行完畢。因此在虛擬機中第一個被執行的<clinit>()方法的類肯定有java.lang.object。
  5. 由父類的<clinit>()方法先執行,也就意味著父類中定義的靜態語句塊要優先於子類的變數賦值操作。
  6. <clinit>()方法對於類或介面來說並不是必須的,如果一個類中沒有靜態語句塊,也沒有對變數的賦值操作,那麼編譯器可以不為這個類生成<clinit>()方法
  7. 虛擬機會保證一個類的<clinit>()方法在多個線程環境中正確地加鎖,同步。

  

 類載入器

  一、類與類載入器

  對於任意一個類,需要由載入它的載入器和這個類本身一同確立其在Java虛擬機中的唯一性,每一個類載入器,都擁有一個獨立的類名稱空間。

  二、雙親委派模型

  (1)從Java虛擬機的角度來講,只存在兩種不同的類載入器:一種是啟動類載入器(Bootstrap Class ClassLoader),這個類載入器使用C++語言實現是Java虛擬機自動的一部分;另一種就是所有其他的類載入器,這些類載入器都由Java語言實現,獨立於虛擬機外部,並且全都是繼承自抽象類java.lang.classLoader.

  (2)細分:啟動類載入器(Bootstrap ClassLoader)

        擴展類載入器(Extension ClassLoadert

           應用程式類載入器(Application ClassLoader)[系統類載入器]

  (3)雙親委派模型工作過程:

    如果一個類載入器收到了類載入器的請求,它首先不會自己去嘗試載入這個類,而是把這個請求委派給父類載入器去完成,每一個層次的類載入器都是如此,因此所有的載入請求最終都應該傳送到頂層類載入器中只有當父類載入器反饋自己無法完成這個類載入請求時,子類載入器才會嘗試自己去載入。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ASP.NET Core在啟動以及後續針對每個請求的處理過程中的各個環節都需要相應的組件提供相應的服務,為了方便對這些組件進行定製,ASP.NET通過定義介面的方式對它們進行了“標準化”,我們將這些標準化的組件稱為服務,ASP.NET在內部專門維護了一個DI容器來提供所需的服務。要瞭解這個DI容器以... ...
  • ??二元操作符在對first??second求值時,大致會經歷以下步驟: 1)對first進行求值; 2)如果結果非空,則該結果就是整個表達式的結果; 3)否則求second的值,其結果作為整個表達式的結果。 例如: ...
  • 當我們初學Winform的時候被其神奇的事件功能所吸引,當點擊一個按鈕時,便會跳到我們所寫的點擊方法當中去。然而這並不符合我們對方法的理解,究竟.net在後面幫助我們實現了什麼。我們怎樣模擬其事件的實現呢。下麵先從Button的Click方法說起。 1.首先查看設計器自動生成的代碼 EventHan ...
  • 目錄結構: 1. SVN伺服器搭建和使用-VisualSVNServer 2. SVN客戶端安裝和使用-TortoiseSVN 3. TortoiseSVN使用方法 SVN簡介 SVN是Subversion的簡稱,是一個開放源代碼的版本控制系統,相較於RCS、CVS,它採用了分支管理系統,它的設計目 ...
  • 1,.NET Framework:是開發平臺,包含兩大部分: ①龐大的代碼庫(類庫),可以在客戶語言(C#,VB)中來使用這些代碼 ②Common Language Runtime,負責管理應用程式的執行 2,使用.NET Framework編寫應用程式,就是使用.NET 代碼庫編寫程式。 3,C# ...
  • 0x00 前言 關於TDD測試驅動開發的文章已經有很多了,但是在游戲開發尤其是使用Unity3D開發游戲時,卻聽不到特別多關於TDD的聲音。那麼本文就來簡單聊一聊TDD如何在U3D項目中使用以及如何使用U3D 5.3.X之後版本已經集成的單元測試模塊Editor Test Runner。 0x01 ...
  • 為什麼要以對象的方式來訪問xml數據表? 還記得,自己是在一次完成師兄佈置的任務時接觸到了xml,那時候需要用xml來作為數據文件,保存一個簡單的圖書管理系統的數據。於是就知道了,可以用xml文件來保存數據(而且比用簡單的文本文件保存數據規範的多,在訪問與讀取數據上面都十分方便),就這樣使用xml的 ...
  • 1.需求 寫一個基於memcache的cache模塊, 需要在key前面加上特定的首碼, 所以user cache的原始的store函數應該寫成 由於加首碼的操作(key_encode/1)是所有存入cache前必須要做的事, 所以我們可以考慮通過metaprogramming來定義一個行為叫bef ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...