Java虛擬機裝載和初始化一個class類代碼解析
在 java 應(yīng)用程序開發(fā)中,只有被 java 虛擬機裝載的 Class 類型才能在程序中使用。只要生成的字節(jié)碼符合 java 虛擬機的指令集和文件格式,就可以在 JVM 上運行,這為 java 的跨平臺性提供條件。下面,我們來看看虛擬機是如何裝載和初始化一個 class 類的。
裝載一個類
學(xué)習(xí)過C/C++語言的讀者知道,C/C++源代碼必須首先別編譯成本地的機器代碼,然后還需要一個鏈接代碼過程。該鏈接過程的主要任務(wù)就是:合并不同的源碼文件產(chǎn)出的中間代碼,并最終獲得一個可直接執(zhí)行的應(yīng)用程序。然后,Java語言不是這么做的,Java應(yīng)用中類似于鏈接過程的步驟是在字節(jié)碼被裝載到JVM中之后再執(zhí)行的。
正如我們所知,JVM存在不止一個類加載器,不同的加載器使用不同的方式來加載類。但是,它們都只在必須加載類時,才開始裝載類。當(dāng)然,如果已裝載完畢的類引用了某些未裝載的類,類裝載器會進一步去裝載這些類,整個的裝載過程是遞歸的。
裝載時機與方式
在Java中,類的裝載策略是由類加載器控制的。我們使用下面這個簡單的示例代碼來演示類的裝載方式與時機:
// TestLoader.java package compiler; public class TestLoader { public static void main(String[] args) { System.out.println("test"); } }
// A.java package compiler; public class A { public void method(){ System.out.println("inside of A"); } }
再看一下它們的目錄結(jié)構(gòu):
|-src |--compiler |------A.java |------TestLoader.java
為了獲得每個類加載的信息,我們可以使用如下的命令來運行程序。其中的 “-verbose:class” 參數(shù)告訴 JVM 打印出每次加載類的信息。
java -verbose:class -classpath /home/ron/workspace/UltimateTest/bin/ compiler.TestLoader
整個程序的輸出信息很繁瑣,我們摘取其中重要的部分展示如下:
[Loaded sun.misc.JavaSecurityProtectionDomainAccess from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.ProtectionDomain$2 from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.ProtectionDomain$Key from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.Principal from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded compiler.TestLoader from file:/home/xiwang/workspace/UltimateTest/bin/] test [Loaded java.lang.Shutdown from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.lang.Shutdown$Lock from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
現(xiàn)在,假設(shè)我們把 TestLoader.java 修改成如下所示:
package compiler; public class TestLoader { public static void main(String[] args) { System.out.println("test"); A a = new A(); a.method(); } }
再次執(zhí)行同樣的運行命令,我們獲得輸出結(jié)果變成如下所示:
[Loaded sun.misc.JavaSecurityProtectionDomainAccess from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.ProtectionDomain$2 from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.ProtectionDomain$Key from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.security.Principal from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded compiler.TestLoader from file:/home/xiwang/workspace/UltimateTest/bin/] test [Loaded compiler.A from file:/home/xiwang/workspace/UltimateTest/bin/] inside of A [Loaded java.lang.Shutdown from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar] [Loaded java.lang.Shutdown$Lock from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
讀者可仔細查看兩者的區(qū)別,可以發(fā)現(xiàn)只有當(dāng) 類A 被使用時,該類對應(yīng)的 A.class 才會被裝載??偨Y(jié)起來,一個類的加載條件是:
(1) 當(dāng)使用 new 操作符執(zhí)行某類時。比如 SomeClass some = new SomeClass()。
(2)當(dāng)已加載類中有一個靜態(tài)引用指向某類時。 比如 System.out 。
初始化時機與方式
在Java中,一個類被加載完畢后,不會立即執(zhí)行類的初始化工作。當(dāng)類中的符號被第一次使用時,該類才開始被初始化。在初始化順序方面:JVM會首先完成父類的初始化,再執(zhí)行子類的初始化;對于類中靜態(tài)的常量,會按照定義的先后順序完成初始化;最后會保證在初始化之前,每個屬性都會有一個默認值。至于類中各種類型成員的初始化順序細節(jié),建議查看本站的這篇文章。
總結(jié)
以上就是本文關(guān)于虛擬機如何裝載和初始化一個Java class類的全部內(nèi)容,希望對您有所幫助。
感謝大家對本站的支持!
相關(guān)文章
springboot實現(xiàn)上傳并解析Excel過程解析
這篇文章主要介紹了springboot實現(xiàn)上傳并解析Excel過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09spring?boot+mybatis-plus配置讀寫分離的操作
這篇文章主要介紹了spring?boot+mybatis-plus配置讀寫分離的操作,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-01-01使用feign調(diào)用接口時調(diào)不到get方法的問題及解決
這篇文章主要介紹了使用feign調(diào)用接口時調(diào)不到get方法的問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03Java編程Socket實現(xiàn)多個客戶端連接同一個服務(wù)端代碼
這篇文章主要介紹了Java編程Socket實現(xiàn)多個客戶端連接同一個服務(wù)端代碼,具有一定參考價值,需要的朋友可以了解下。2017-11-11使用Java快速將Web中表格轉(zhuǎn)換成Excel的方法
在平時做系統(tǒng)項目時,經(jīng)常會需要做導(dǎo)出功能,下面這篇文章主要給大家介紹了關(guān)于使用Java快速將Web中表格轉(zhuǎn)換成Excel的相關(guān)資料,需要的朋友可以參考下2023-06-06java組件smartupload實現(xiàn)上傳文件功能
這篇文章主要為大家詳細介紹了java組件smartupload實現(xiàn)上傳文件功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-10-10