JVM原理之類加載的全過程
JVM原理-類加載過程
Java類加載過程
可以看作是將我們寫的代碼(以class文件的形式)轉(zhuǎn)化為可以運(yùn)行的程序。
這過程分為幾個步驟:加載、鏈接、初始化、使用和卸載。
1.加載:找到并打開書
- 過程:從書架上找到你要的書,把它拿到桌子上,準(zhǔn)備閱讀。
- 對應(yīng)Java的過程:JVM從硬盤上找到編譯好的class文件(如Dog.class),然后把它讀入內(nèi)存里,生成一個Class對象。
- Class對象:這個對象包含了類的各種信息,比如類名、方法、字段等,相當(dāng)于一本被打開的書。
2. 鏈接:檢查書的內(nèi)容和準(zhǔn)備好工具
鏈接階段包括驗(yàn)證、準(zhǔn)備和解析三個步驟:
驗(yàn)證:檢查書里的內(nèi)容是否有錯誤。
- 對應(yīng)Java的過程:檢查class文件的格式和內(nèi)容是否合法,確保沒有語法錯誤或其他問題。
- 如果有錯誤,程序會拋出異常,無法繼續(xù)運(yùn)行。
準(zhǔn)備:為靜態(tài)變量分配內(nèi)存并初始化為默認(rèn)值。
- 對應(yīng)Java的過程:靜態(tài)變量在這個階段被分配內(nèi)存,并初始化為默認(rèn)值。
- 例如,static int a;會被初始化為0。
解析(可選):把間接引用轉(zhuǎn)換為直接引用。
- 對應(yīng)Java的過程:把符號引用(指向類、方法、字段的字符串)
- 轉(zhuǎn)換為直接引用(內(nèi)存地址),方便后續(xù)快速訪問。
3. 初始化:翻開書并開始閱讀
過程:正式開始根據(jù)書里的內(nèi)容進(jìn)行設(shè)置和操作。
對應(yīng)Java的過程:執(zhí)行類的初始化,包括:
- 靜態(tài)變量的賦值:將靜態(tài)變量賦值為代碼中定義的值。例如,static int a = 10;,此時a會被設(shè)置為10。
- 靜態(tài)代碼塊的執(zhí)行:依次執(zhí)行靜態(tài)代碼塊中的代碼。靜態(tài)代碼塊可以用于復(fù)雜的初始化工作。
- 順序:靜態(tài)變量和靜態(tài)代碼塊的初始化按照它們在代碼中出現(xiàn)的順序進(jìn)行。
4. 使用:開始利用書中的信息
- 過程:根據(jù)書中的指導(dǎo)完成具體任務(wù)。
- 對應(yīng)Java的過程:實(shí)際使用類和對象,包括創(chuàng)建實(shí)例和調(diào)用方法。
- 對象創(chuàng)建:如new Dog(),JVM會在堆內(nèi)存中為Dog對象分配空間。
步驟:
- 分配內(nèi)存:為新對象分配內(nèi)存。
- 設(shè)置默認(rèn)值:對象的屬性被初始化為默認(rèn)值(如數(shù)字為0,對象引用為null)。
- 執(zhí)行初始化代碼:按照代碼中定義的順序?yàn)閷傩再x值。
- 執(zhí)行構(gòu)造函數(shù):運(yùn)行構(gòu)造函數(shù),進(jìn)行進(jìn)一步初始化和操作。
5. 卸載:書用完后放回書架
- 過程:書看完了,把它合上,放回書架,不再需要它了。
- 對應(yīng)Java的過程:當(dāng)類不再需要時,JVM會把類從內(nèi)存中卸載,釋放占用的資源。
- 垃圾回收:JVM的垃圾回收機(jī)制會自動檢測不再使用的類和對象,并回收它們占用的內(nèi)存。
對類初始化的5種情況
根據(jù)JVM規(guī)范,類初始化的情況有且只有以下5種:
- 創(chuàng)建類的實(shí)例:當(dāng)我們用new來創(chuàng)建類的對象時,比如new Dog(),如果這個類還沒有被初始化,那么它必須先初始化才能創(chuàng)建對象。
- 調(diào)用類的靜態(tài)方法:比如Dog.bark(),靜態(tài)方法屬于類本身而不是某個對象,因此在調(diào)用時,類必須先初始化。
- 訪問類或接口的靜態(tài)變量:當(dāng)我們訪問類的靜態(tài)變量時,比如Dog.age,這也會導(dǎo)致類的初始化。
- 使用Class.forName()方法:這種方法會強(qiáng)制初始化一個類。比如Class.forName("Dog")會讓Dog類被加載并初始化。
- 類加載器啟動主類:當(dāng)我們運(yùn)行一個程序時,比如執(zhí)行java DogMain,JVM會先初始化DogMain類并執(zhí)行它的main方法。
符號引用和直接引用的區(qū)別是什么?
- 符號引用:可以理解為一種間接的引用,它并不指向內(nèi)存中的具體位置。相當(dāng)于書里提到了某個章節(jié),但沒有告訴你具體在哪一頁。
- 直接引用:是內(nèi)存中的具體地址,也就是可以直接找到的目標(biāo)地址。相當(dāng)于書里直接標(biāo)明某個章節(jié)在第幾頁。
類變量和實(shí)例變量
類變量(靜態(tài)變量)
- 定義:使用static關(guān)鍵字修飾的變量。
- 歸屬:屬于類本身,而不是某個特定的對象。
- 共享性:所有實(shí)例共享同一個類變量。如果一個實(shí)例修改了類變量的值,其他實(shí)例也會看到這個變化。
- 生命周期:在類加載時被初始化,直到類卸載時被回收。其存儲在方法區(qū)(Method Area)。
- 訪問方式:可以通過類名直接訪問,也可以通過實(shí)例訪問,但推薦使用類名進(jìn)行訪問。
實(shí)例變量
- 定義:沒有使用static關(guān)鍵字修飾的變量。
- 歸屬:屬于類的每個實(shí)例,每個實(shí)例都有自己獨(dú)立的一份實(shí)例變量。
- 獨(dú)立性:每個實(shí)例的實(shí)例變量相互獨(dú)立,一個實(shí)例的實(shí)例變量變化不會影響其他實(shí)例的實(shí)例變量。
- 生命周期:在對象創(chuàng)建時被初始化,直到對象被垃圾回收時被回收。其存儲在堆內(nèi)存(Heap Memory)。
- 訪問方式:只能通過對象實(shí)例來訪問,不能通過類名直接訪問。
Class.forName()
Class.forName()的主要作用是 動態(tài)加載類,尤其是在需要根據(jù)類名字符串來加載類的情況下(比如 JDBC 驅(qū)動程序、反射等)。
這提供了一種靈活的方式,允許你在運(yùn)行時加載類,而不是在編譯時綁定類。
當(dāng)你調(diào)用這個方法時,JVM 會嘗試根據(jù)你傳遞的類名(作為字符串)加載該類,并且會執(zhí)行該類的靜態(tài)代碼塊(如果有的話)。
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java String類簡單用法實(shí)戰(zhàn)示例【字符串輸出、比較】
這篇文章主要介紹了Java String類簡單用法,結(jié)合具體實(shí)例形式分析了Java使用String類實(shí)現(xiàn)字符串的輸出和比較功能相關(guān)操作技巧,需要的朋友可以參考下2019-07-07詳解配置spring-boot-actuator時候遇到的一些小問題
這篇文章主要介紹了詳解配置spring-boot-actuator時候遇到的一些小問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11sql于navicat中能運(yùn)行在mybatis中不能運(yùn)行的解決方案
這篇文章主要介紹了sql于navicat中能運(yùn)行在mybatis中不能運(yùn)行的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01java訪問者模式的靜態(tài)動態(tài)及偽動態(tài)分派徹底理解
這篇文章主要為大家介紹了java訪問者模式的靜態(tài)動態(tài)及偽動態(tài)分派徹底理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06java 出現(xiàn)Zipexception 異常的解決辦法
這篇文章主要介紹了java 出現(xiàn)Zipexception 異常的解決辦法的相關(guān)資料,出現(xiàn) java.util.zip.ZipException: error in opening zip file 異常的原因及解決方法,需要的朋友可以參考下2017-08-08springboot + JPA 配置雙數(shù)據(jù)源實(shí)戰(zhàn)
這篇文章主要介紹了springboot + JPA 配置雙數(shù)據(jù)源實(shí)戰(zhàn),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09