JVM 之類載入器

来源:https://www.cnblogs.com/lyuzt/archive/2019/12/24/12057385.html
-Advertisement-
Play Games

一、什麼是 JVM JVM(Java Virtual Machine)是一個可以執行 Java 位元組碼文件(即 .class 文件)的虛擬機進程。當 Java 源文件能被成功編譯成 .class 文件,就能在不同平臺上的不同版本的 JVM 運行,因為 JVM 能將相同的 .class 文件解釋稱不同 ...


一、什麼是 JVM

  JVM(Java Virtual Machine)是一個可以執行 Java 位元組碼文件(即 .class 文件)的虛擬機進程。當 Java 源文件能被成功編譯成 .class 文件,就能在不同平臺上的不同版本的 JVM 運行,因為 JVM 能將相同的 .class 文件解釋稱不同平臺的機器碼。正是因為 JVM 的存在,Java 被稱為與平臺無關的語言。

  一般而言,.java 文件經過編譯後會得到 .class 文件,而將這個文件載入到記憶體之前需要先通過類載入器,先簡單過一下圖:

            

二、類載入過程

  類載入的過程為: 載入-->連接(驗證-->準備-->解析)-->初始化。下麵介紹其中的幾個過程。

 1、載入

  這個過程主要是通過類的全限定名,例如 java.lang.String 這樣帶上包路徑的類名,獲取到位元組碼文件;然後將這個位元組碼文件代表的靜態存儲結構(可簡單理解為對象創建的模板)存在方法區,併在堆中生成一個代表此類的 Class 類型的對象,作為訪問方法區中“模板”的入口,往後創建對象的時候就按照這個模板創建。

  舉個例子,有時候通過反射創建對象,像當初學 JDBC 時會通過 Class.getName("com.mysql.jdbc.Driver.class").newInstance() 創建對象,通過 Class 和相應的全限定類名獲取到方法區中的“模板”然後創建對象。

        

 2、驗證

  驗證過程主要確保被載入的類的正確性。首先要先驗證文件格式是否規範,如果只是通過 .class 尾碼來辨別,那隨便把尾碼名改一下就可以跑程式了,那豈不是很容易出事。來看看位元組碼文件大概是長什麼樣的:

       

 

  註意看首碼 cafe babe(咖啡寶貝?)這隻是驗證的其中一個點,還會驗證位元組碼文件里是否包含主次版本號等驗證信息。

 3、準備

  這個階段主要是給類變數(靜態變數)分配方法區的記憶體並初始化。實例變數不是在這個階段分配記憶體,實例變數是隨著對象一起分配在堆中。另外,給靜態變數初始化為零值或空值,比如public static int n=5;這裡並不是馬上給 n 這個變數賦值為 5,而是先將其賦值為 0,類似的,如果是引用數據類型,則預設為 null。還有一點需要註意的是,對於 final 類型的數據,必須在程式內給它賦值,系統不會自動初始化,例如 static String str = "hello" + “world”;String 是 final 類型的,在編譯階段就給它優化成 static String str = "helloworld” ,並且將 "helloworld" 放進了常量池。

 4、初始化

  這個階段就是將靜態變數賦值為初始值,還是 public static int n=5; 這回給 n 賦值為 5 了。

三、類載入器

        

  啟動類載入器是由C/C++寫的,主要負責載入 jre\lib 目錄下的類;擴展類載入器主要負責載入 jre\lib\ext 目錄下的類;而應用程式類載入器主要負責載入我們自己編寫的類;當然還能自己寫類載入器,即自定義載入器。程式主要由前面三個類載入器相互配合載入的。

public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        System.out.println(main.getClass().getClassLoader());
        System.out.println(main.getClass().getClassLoader().getParent());
        System.out.println(main.getClass().getClassLoader().getParent().getParent());
    }
}  

  由於啟動類載入器是 C/C++ 語言寫的,所以輸出為 null

 雙親委派機制

  在類載入的過程中,存在著雙親委派機制,即當要載入一個類時,先由父類載入器載入,當父類載入器沒辦法載入時,才由下麵的載入器載入,來看一個程式:

package java.lang;   // 自定義的包

public class String {
    public static void main(String[] args) {
        System.out.println("這是自定義的java.lang.String類");
    }
}

  

  由於 jre\lib\ext 中存在 java.lang.String 類,當載入該類的時候,根據全限定名進行查找,找到後由啟動類載入器載入,發現 String 類中不包含 main() 方法,因此程式出錯。 


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

-Advertisement-
Play Games
更多相關文章
  • 首先用一個例子指出來constructor存在形式。 由上面的代碼我們總結出結論1:上面的代碼在控制台可以看出constructor是指向構造器Fruit的引用。 這個地方就有點奇怪了。這個constructor到底指向的是那個實例的構造器? 根據上面的代碼總結出結論2:constructor指向的 ...
  • 導讀 篇幅較長,乾貨十足,閱讀需要花點時間,全部手打出來的字,難免出現錯別字,敬請諒解。珍惜原創,轉載請註明出處,謝謝~! NoSql介紹與Redis介紹 什麼是Redis? Redis是用C語言開發的一個開源的高性能鍵值對(key-value)記憶體資料庫。 它提供五種數據類型來存儲值:字元串類型、 ...
  • 2019/12/24 | 在校大二上學期 | 太原科技大學 初學java後,我們會發現java難點不在於Java語法難學,而是把我們掛在瞭如何設計類的“弔繩”上了。這恰恰也是小白與入職多年的程式員的的差距之一。所以今天來分享一下我的觀點: 那麼如何設計類呢?有沒有遵循的原則可言呢?答案呢,就是下麵的 ...
  • 什麼是NServiceBus?NServiceBus 是一個用於構建企業級 .NET系統的開源通訊框架。它在消息發佈/訂閱支持、工作流集成和高度可擴展性等方面表現優異,因此是很多分散式系統基礎平臺的理想選擇。它能夠幫助開發人員在搭建企業.NET系統時避免很多典型的常見問題。同時,該框架也提供了一些可 ...
  • WEB API的應用場景非常豐富,例如:將已有系統的功能或數據開放給合作伙伴或生態圈;對外發佈可嵌入到其他網頁的微件;構建前後端分離的WEB應用;開發跨不同終端的移動應用;集成公司內部不同系統等等。在上述場景里,你可能是WEB API的使用者,也可能是設計者,但你知道如何評判WEB API的優劣嗎? ...
  • 一、socketserver模塊簡介 socketserver模塊簡化了網路編程,模塊下有五個服務類:BaseServer、TCPServer、UDPServer、UnixStreamServer、UnixDatagramServer 。這五個類的關係如下: + + | BaseServer | + ...
  • 一、首部欄位或者消息頭 1.下麵幾個類型都是請求的: User-Agent:關於瀏覽器和它平臺的消息,如Mozilla5.0 Accept:客戶端能處理的頁面的類型,如text/html Accept-Charset:客戶端可以接受的字元集,如unicode-1-1 Accept-Encoding: ...
  • 問題:文件上傳時候需要驗證上傳的文件是否合法,文件偽裝如何識別? 一個簡單測試:把txt文件尾碼直接改成jpg;上傳 1.通過$_FILES['userfile']['type'];獲取文件尾碼名; T_T 沒有檢測出來; 2.用pathinfo()函數來獲取文件路徑的信息 T_T 沒有檢測出來; ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...