溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JVM運(yùn)行與類加載的示例分析

發(fā)布時(shí)間:2021-08-25 11:38:27 來源:億速云 閱讀:134 作者:小新 欄目:編程語言

這篇文章主要介紹了JVM運(yùn)行與類加載的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

為什么要使用類加載器?

Java語言里,類加載都是在程序運(yùn)行期間完成的,這種策略雖然會(huì)令類加載時(shí)稍微增加一些性能開銷,但是會(huì)給java應(yīng)用程序提供高度的靈活性。例如:

1.編寫一個(gè)面向接口的應(yīng)用程序,可能等到運(yùn)行時(shí)再指定其實(shí)現(xiàn)的子類;

2.用戶可以自定義一個(gè)類加載器,讓程序在運(yùn)行時(shí)從網(wǎng)絡(luò)或其他地方加載一個(gè)二進(jìn)制流作為程序代碼的一部分;(這個(gè)是Android插件化,動(dòng)態(tài)安裝更新apk的基礎(chǔ))

為什么研究類加載全過程?

  • 有助于連接JVM運(yùn)行過程

  • 更深入了解java動(dòng)態(tài)性(解熱部署,動(dòng)態(tài)加載),提高程序的靈活性

類加載機(jī)制

JVM把class文件加載到內(nèi)存,并對數(shù)據(jù)進(jìn)行校驗(yàn)、解析和初始化,最終形成JVM可以直接使用的java類型的全過程。

JVM運(yùn)行與類加載的示例分析

加載

將class文件字節(jié)碼內(nèi)容加載到內(nèi)存中,并將這些靜態(tài)數(shù)據(jù)轉(zhuǎn)換成方法區(qū)中的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu),在堆中生成一個(gè)代表這個(gè)類的java.lang.Class對象,作為方法區(qū)類數(shù)據(jù)的訪問入口,這個(gè)過程需要類加載器參與。

JVM運(yùn)行與類加載的示例分析

鏈接

將java類的二進(jìn)制代碼合并到JVM的運(yùn)行狀態(tài)之中的過程

  • 驗(yàn)證: 確保加載的類信息符合JVM規(guī)范,沒有安全方面的問題

  • 準(zhǔn)備: 正式為類變量(static變量)分配內(nèi)存并設(shè)置類變量初始值的階段,這些內(nèi)存都將在方法去中進(jìn)行分配

  • 解析: 虛擬機(jī)常量池的符號引用替換為字節(jié)引用過程

初始化

  • 初始化階段是執(zhí)行類構(gòu)造器<clinit>()方法的過程。類構(gòu)造器<clinit>()方法是由編譯器自動(dòng)收藏類中的所有類變量的賦值動(dòng)作和靜態(tài)語句塊(static塊)中的語句合并產(chǎn)生

  • 當(dāng)初始化一個(gè)類的時(shí)候,如果發(fā)現(xiàn)其父類還沒有進(jìn)行過初始化,則需要先觸發(fā)其父類的初始化

  • 虛擬機(jī)會(huì)保證一個(gè)類的<clinit>()方法在多線程環(huán)境中被正確加鎖和同步

  • 當(dāng)范圍一個(gè)Java類的靜態(tài)域時(shí),只有真正聲名這個(gè)域的類才會(huì)被初始化

例1:

public class Demo01 {
 public static void main(String[] args) {
  A a = new A();
  System.out.println(a.width);
 }
}

class A{
 public static int width=100; //靜態(tài)變量,靜態(tài)域 field
 static{
  System.out.println("靜態(tài)初始化類A");
  width = 300 ;
 }
 public A() {
  System.out.println("創(chuàng)建A類的對象");
 }
}

分析:

JVM運(yùn)行與類加載的示例分析

說明:

內(nèi)存中存在棧、堆(放創(chuàng)建好的對象)、方法區(qū)(實(shí)際也是一種特殊堆)

1、JVM加載Demo01時(shí)候,首先在方法區(qū)中形成Demo01類對應(yīng)靜態(tài)數(shù)據(jù)(類變量、類方法、代碼…),同時(shí)在堆里面也會(huì)形成java.lang.Class對象(反射對象),代表Demo01類,通過對象可以訪問到類二進(jìn)制結(jié)構(gòu)。然后加載變量A類信息,同時(shí)也會(huì)在堆里面形成a對象,代表A類。

2、main方法執(zhí)行時(shí)會(huì)在棧里面形成main方法棧幀,一個(gè)方法對應(yīng)一個(gè)棧幀。如果main方法調(diào)用了別的方法,會(huì)在棧里面挨個(gè)往里壓,main方法里面有個(gè)局部變量A類型的a,一開始a值為null,通過new調(diào)用類A的構(gòu)造器,棧里面生成A()方法同時(shí)堆里面生成A對象,然后把A對象地址付給棧中的a,此時(shí)a擁有A對象地址。

3、當(dāng)調(diào)用A.width時(shí),調(diào)用方法區(qū)數(shù)據(jù)。

當(dāng)類被引用的加載,類只會(huì)加載一次

類的主動(dòng)引用(一定會(huì)發(fā)生類的初始化)

  • new一個(gè)類的對象

  • 調(diào)用類的靜態(tài)成員(除了final常量)和靜態(tài)方法

  • 使用java.lang.reflect包的方法對類進(jìn)行反射調(diào)用

  • 當(dāng)虛擬機(jī)啟動(dòng),java Demo01,則一定會(huì)初始化Demo01類,說白了就是先啟動(dòng)main方法所在的類

  • 當(dāng)初始化一個(gè)類,如果其父類沒有被初始化,則先初始化它父類

類的被動(dòng)引用(不會(huì)發(fā)生類的初始化)

  • 當(dāng)訪問一個(gè)靜態(tài)域時(shí),只有真正聲名這個(gè)域的類才會(huì)被初始化

  • 通過子類引用父類的靜態(tài)變量,不會(huì)導(dǎo)致子類初始化

  • 通過數(shù)組定義類的引用,不會(huì)觸發(fā)此類初始化

  • 引用常量不會(huì)觸發(fā)此類的初始化(常量在編譯階段就存入調(diào)用類的常量池中了)

例2:

public class Demo01 {
 static{
  System.out.println("靜態(tài)初始化Demo01");
 }
 
 
 public static void main(String[] args) throws Exception {
  System.out.println("Demo01的main方法!");
  System.out.println(System.getProperty("java.class.path"));
  
  //主動(dòng)引用
//  new A();
//  System.out.println(A.width);
//  Class.forName("com.sinosoft.test.A");
  
  
  //被動(dòng)引用
//  System.out.println(A.MAX);
//  A[] as = new A[10];
  System.out.println(B.width);//B類不會(huì)被加載
  
 }
}

class B extends A {
 static {
  System.out.println("靜態(tài)初始化B");
 }
}

class A extends A_Father {
 public static int width=100; //靜態(tài)變量,靜態(tài)域 field
 public static final int MAX=100; 
 
 static {
  System.out.println("靜態(tài)初始化類A");
  width=300;
 }
 public A(){
  System.out.println("創(chuàng)建A類的對象");
 }
}

class A_Father extends Object {
 static {
  System.out.println("靜態(tài)初始化A_Father");
 }
}

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“JVM運(yùn)行與類加載的示例分析”這篇文章對大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

jvm
AI