Java類的載入機制
1.jvm和類的關係
當呼叫java命令執行一個java程式時,必會啟動一個jvm,該java程式的所有執行緒、變數都處於jvm中,都使用該jvm
的記憶體區。
jvm的終止情況:
- 程式自然執行結束;
- 程式執行過程中,遇到System.exit();Runtime.getRuntime.exit();
- 程式執行過程中,遇到未捕獲的異常或錯誤時;
- 程式所在的平臺強制結束了jvm程序。
2.類的載入過程
類的生命週期
類從被載入到虛擬機器記憶體開始,到卸載出記憶體為止,它的生命週期如下所示,可劃分為七個階段:
載入、驗證、準備、初始化和解除安裝這五個階段順序時固定的,類的載入過程必須按照這種順序開始。但是解析階段不一定,它在某種情況下,可以在初始化之後再開始,這是為了在執行時動態繫結某些特性(例如:介面只有在呼叫的時候才知道具體實現的是哪個子類)。這些階段通常都是互相交叉混合式進行的,一個階段執行的過程中往往會啟用另外一個階段。
載入階段
載入階段是“類載入機制”中的一個階段,亦稱“裝載”,主要完成:
- 通過“類全名”來獲取定義此類的二進位制位元組流;
- 將位元組流所代表的靜態儲存結構轉換為方法區的執行時資料結構;
- 在java堆中生成一個代表這個類的java.lang.Class物件,作為方法區這些資料的訪問入口。
載入階段完成後,虛擬機器外部的二進位制位元組流就按照虛擬機器所需要的格式儲存在方法區中,方法區中的資料儲存格式由虛擬機器自行定義,虛擬機器並未規定此區域的具體資料結構。然後在java堆中例項化一個java.lang.Class類的物件,這個物件作為程式訪問方法區中這些資料結構的外部介面。
驗證階段
驗證是連結階段的第一步,這一步主要的目的是確保class檔案的位元組流中包含的資訊符合當前虛擬機器的要求,並且不會危害到虛擬機器的自身安全。
包括四個驗證過程:
- 檔案格式驗證:驗證位元組流是否符合Class檔案格式的規範,並且能被當前版本的虛擬機器處理。主要目的是保證輸入的位元組流能正確地解析並存儲於方法區之內,格式上符合描述一個Java型別資訊的要求。這階段的驗證是基於二進位制位元組流進行的,只有通過這個階段的驗證後,位元組流才會進入記憶體的方法區中進行儲存,所以後面的3個驗證階段全部是基於方法區的儲存結構進行的,不會再直接操作位元組流。
- 元資料驗證:對位元組碼描述的資訊進行語義分析,以保證其描述的資訊符合Java語言規範的要求,主要目的是對類的元資料資訊進行語義校檢,保證不存在不符合Java語言規範的元資料資訊。
- 位元組碼驗證:主要目的是通過資料流和控制流分析,確定程式語義是合法的、符合邏輯的。在第二階段對元資料資訊中的資料型別做完校驗後,這個階段將對類的方法體進行校驗分析,保證被校驗類的方法在執行時不會做出危害虛擬機器安全的事件。
- 符號引用驗證:發生在虛擬機器將符號引用轉化為直接引用的時候,這個轉化動作將在來連結的第三個階段--解析階段中發生。符號引用驗證可以看做是對類自身以外(常量池中的各種符號引用)的資訊進行匹配性校驗,通常需要校驗下列內容:符號引用中通過字串描述的全限定名是否能找到對應的類;在指定類中是否存在符合方法的欄位描述符以及簡單名稱所描述的方法和欄位;符號引用中的類、欄位、方法的訪問性(private、protected、public、default)是否可以被當前類訪問。
準備階段
準備階段是正式為類變數分配記憶體並設定類變數初始值的階段,這些變數所使用的記憶體都將在方法區進行分配。注意:這時候進行記憶體分配的僅包括類變數(被static修飾的變數),而不包括例項變數,例項變數將會在物件例項化時隨著物件一起分配在Java堆中。其次,這裡所說的“通常情況”下是資料型別的零值,假設一個類變數的定義為:
public static int value = 123;
變數value在準備階段過後的初始值為0而不是123,因為把value賦值為123的putstatic指令是程式被編譯後,存放在類構造器<client>()方法之中,所以賦值動作將會在初始化階段才會執行,下表列出了Java中所有基本資料的零值。
資料型別 | 零 值 | 資料型別 | 零 值 |
int | 0 | boolean | false |
long | 0L | float | 0.0f |
short | (short)0 | double | 0.0d |
char | '\u0000' | reference | null |
byte | (byte)0 |
特殊情況:如果類欄位的屬性表中存在ConstantValue屬性,那在準備階段變數value就會被初始化為ConstantValue屬性所指定的值,假設上面類變數value的定義變為:
public static final int value = 123;
編譯時javac將會為value生成ConstantValue屬性,在準備階段虛擬機器就會根據ConstantValue的設定將value賦值為123。
解析階段
解析階段是虛擬機器將常量池中的符號引用替換為直接引用的過程,解析動作主要針對類或介面、欄位、類方法、介面方法、方法型別、方法控制代碼和呼叫點限定7類符號引用進行。
- 符號引用:以一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能無歧義地定位到目標即可。符號引用與虛擬機器實現的記憶體佈局無關,引用的目標並不一定已經載入到記憶體中。各種虛擬機器實現的記憶體佈局可以各不相同,但是它們接收的符號引用必須都是一致的,因為符號引用的字面量形式明確定義在Java虛擬機器規範的Class檔案格式中。
- 直接引用:直接引用可以是直接指向目標的指標、相對偏移量或是一個能間接定位到目標的控制代碼。直接引用是和虛擬機器實現的記憶體佈局相關的,同一個符號引用在不同虛擬機器例項上翻譯出來的直接引用一般不會相同。如果有了直接引用,那引用的目標必然已經在記憶體中存在。
初始化階段
初始化階段是類載入過程的最後一步,前面的類載入過程,除了在載入階段使用者應用程式可以通過自定義類載入器參與之外,其餘動作完全由虛擬機器主導和控制。到了初始化階段,才真正開始執行類中定義的Java程式程式碼(或者說是位元組碼)。
在準備階段,變數已經賦過一次系統要求的初始值,而在初始化階段,則根據程式設計師通過制定的主觀計劃去初始化類變數和其他資源,初始化階段是執行類構造器<client>()方法的過程,必須進行初始化的5中情況:
- 遇到new、getstatic、putstatic或invokestatic這4條位元組碼指令時,如果類沒有進行過初始化,則需要先觸發其初始化。生成這4條指令最常見的Java程式碼場景:使用new關鍵字例項化物件的時候、讀取或設定一個類的靜態欄位(被final修飾、已在編譯期把結果放入常量池的欄位除外)的時候,以及呼叫一個類的靜態方法的時候。
- 使用java.lang.reflect包的方法對類進行反射呼叫的時候,如果類沒有進行過初始化,則需要先觸發其初始化。
- 當初始化一個類的時候,如果發現其父類還沒有進行過初始化,則需要先觸發其父類的初始化。
- 當虛擬機器啟動時,使用者需要指定一個要執行的主類(包含main()方法的那個類),虛擬機器會先初始化這個類。
- 當使用JDK1.7的動態語言支援時,如果一個java.lang.invoke.MethodHandle例項最後的解析結果RET_getStatic、REF_putStatic、REF_invokeStatic的方法控制代碼,並且這個方法所對應的類沒有進行過初始化,則需要先觸發其初始化。
相關推薦
從阿里巴巴面試題到java類載入機制
首先很經典的阿里巴巴面試題 加上我自己的一些疑惑程式碼 public class Text { public static int k = 0; public final int k1 = 3; //自己加的 public static Text t1 = new Text("
java類載入機制和自定義類載入器
類載入順序 上圖所示的是類載入的順序,按照大的順序可以分為載入、連結、初始化 其中連結又可以分成驗證、準備、解析三個步驟 載入 1.將類的class檔案讀入到記憶體中 載入類檔案的方式有: 1. 本機檔案載入 2.jar包載入 3.網路載入 4.原始檔動態編譯載入
淺談Java類載入機制
最近在學習 Tomcat 架構,其中很重要的一個模組是類載入器,因為以前學習的不夠深入,所以趁這個機會好好把類載入機制搞明白。 概述 類載入器主要分為兩類,一類是 JDK 預設提供的,一類是使用者自定義的。 JDK 預設提供三種類載入器 Bootstrap ClassLo
深入理解Java類載入機制(一)
1 前言: 在上一篇文章一文讓你明白 Java 位元組碼中, 我們瞭解了java位元組碼的解析過程,那麼在接下來的內容中,我們來了解一下類的載入機制。 2 題外話 Java的核心是什麼?當然是JVM了,所以說了解並熟悉JVM對於我們理解Java語言非常重要,不管你是做Java還是Andr
Java 類載入機制詳解
一、類載入器 類載入器(ClassLoader),顧名思義,即載入類的東西。在我們使用一個類之前,JVM需要先將該類的位元組碼檔案(.class檔案)從磁碟、網路或其他來源載入到記憶體中,並對位元組碼進行解析生成對應的Class物件,這就是類載入器的功能。我們可以利用類載入器,實現類的動態載入。 二、類的
Java類載入機制
類載入機制 概念 類載入器把class檔案中的二進位制資料讀入到記憶體中,存放在方法區,然後在堆區建立一個java.lang.Class物件,用來封裝類在方法區內的資料結構。 1、載入: 查詢並載入類的二進位制資料(把class檔案裡面的資訊載入到記憶體裡面) 2
JVM——Java類載入機制
class Singleton{ private static Singleton singleton = new Singleton(); public static int value1; public static int valu
JAVA 類載入機制學習筆記
JAVA 類生命週期 如上圖所示,Java類的生命週期如圖所示,分別為載入、驗證、準備、解析、初始化、使用、解除安裝。其中驗證、準備、解析這三個步驟統稱為連結。 載入:JVM根據全限定名來獲取一段二進位制位元組流,將二進位制流轉化為方法區的執行時資料結構,在記憶體中生成一個代表
【Java面試題】之類載入:從面試題分析Java類載入機制
“載入”(Loading)階段是“類載入”(Class Loading)過程的第一個階段,在此階段,虛擬機器需要完成以下三件事情: 1、 通過一個類的全限定名來獲取定義此類的二進位制位元組流。 2、 將這個位元組流所代表的靜態儲存結構轉化為方法區的執行時資料結
jvm之java類載入機制和類載入器(ClassLoader)的詳解
當程式主動使用某個類時,如果該類還未被載入到記憶體中,則JVM會通過載入、連線、初始化3個步驟來對該類進行初始化。如果沒有意外,JVM將會連續完成3個步驟,所以有時也把這個3個步驟統稱為類載入或類初始化。
Java-類載入機制
Java-類載入機制 摘要 本文簡要介紹Java載入機制,還會介紹雙親委派機制的破壞,執行緒上下文載入器,以及JDBC Driver是如何自動載入的。 未完成 0x01 Java類載入機制 1.1 簡介 當前版本jdk是採用雙親委派機制: 子ClassL
談談 Java 類載入機制
最近在學習 Tomcat 架構,其中很重要的一個模組是類載入器,因為以前學習的不夠深入,所以趁這個機會好好把類載入機制搞明白。 概述 類載入器主要分為兩類,一類是 JDK 預設提供的,一類是使用者自定義的。 JDK 預設提供三種類載入器: Bootstrap
java 類載入機制--類載入時機
相對於看很多父類和子類如何如何初始化的文章,瞭解java虛擬機器的類載入機制之後都會覺得,噢,原來是這個樣子!這裡僅就類的載入時機做個學習筆記,更多內容改日再寫。詳情請看《深入理解java虛擬機器》。 不同於例如c,cpp那些編譯時期就需要進行連線工作的語言,
Java 類載入機制 ClassLoader Class.forName 記憶體管理 垃圾回收GC
類載入是Java程式執行的第一步,研究類的載入有助於瞭解JVM執行過程,並指導開發者採取更有效的措施配合程式執行。 研究類載入機制的第二個目的是讓程式能動態的控制類載入,比如熱部署等,提高程式的靈活性和適應性。 一、簡單過程 Java
Java類載入機制——案例分析
原文連結:http://blog.csdn.net/u013256816/article/details/50837863 在《Java虛擬機器類載入機制》一文中詳細闡述了類載入的過程,並舉了幾個例子進行了簡要分析,在文章的最後留了一個懸念給各位,這裡來揭開這個懸念。建
深入java static關鍵字 淺析java類載入機制(解答java靜態方法或變數無法訪問非靜態資料)
想要清晰理解java語法,不瞭解java和jvm的機制是不行的,以前不理解java中用static修飾方法和變數為什麼不可以訪問非靜態方法和資料,現在明瞭,如果你也有相同的困惑,這篇部落格足以解惑,原創不易,轉載請宣告出處。 本文分為3大部分 static
java 類載入機制
1.java虛擬機器中可以有多個類載入器。 2.系統預設有三個類載入器,每個類載入器負責特定的位置的類載入任務,分別是: BootStrap-->JRE/lib/rt.jar ExtClassLoader-->JRE/lib/ext/*.jar AppClass
阿里面試題,深入理解Java類載入機制
類的生命週期 包括以下 7 個階段: 載入(Loading) 驗證(Verification) 準備(Pr
技術複習-java類載入機制
java類載入過程 裝載 把class位元組碼載入到記憶體中。 連結 驗證、準備、解析 初始化 類的靜態變數、靜態程式碼庫
JVM 第三篇:Java 類載入機制
![](https://cdn.geekdigging.com/java/java_header.jpg) > 本文內容過於硬核,建議有 Java 相關經驗人士閱讀。 ## 1. 什麼是類的載入? 類的載入指的是將類的 .class 檔案中的二進位制資料讀入到記憶體中,將其放在執行時資料區的方法區內,然