目錄
內(nèi)存區(qū)域劃分
JVM中的棧
JVM中的堆
程序計(jì)數(shù)器
方法區(qū)(元數(shù)據(jù)區(qū))
給一段代碼,某個(gè)變量在哪個(gè)區(qū)域上?
類加載
類加載時(shí)機(jī)
雙親委派模型
GC 垃圾回收機(jī)制
GC 實(shí)際工作過程
1.找到垃圾/判定垃圾
1.可達(dá)性分析(Java中的做法)
2.引用計(jì)數(shù)
2.清理垃圾
1.標(biāo)記清除
2.復(fù)制算法
3.標(biāo)記整理
分代回收(復(fù)制算法+標(biāo)記整理)
內(nèi)存區(qū)域劃分
如果內(nèi)存區(qū)域只有一塊,不太方便,為了更加方便使用,就把整個(gè)空間隔成很多區(qū)域,每一個(gè)區(qū)域都有不同的作用
JVM,在啟動(dòng)的時(shí)候,會(huì)申請(qǐng)一整個(gè)很大的區(qū)域,JVM 是一個(gè)應(yīng)用程序,從操作系統(tǒng)里申請(qǐng)內(nèi)存,JVM把整個(gè)空間分層幾個(gè)部分,每個(gè)部分各自有不同的功能作用
每一個(gè)Java進(jìn)程都包含一個(gè)JVM
JVM中的棧
JVM中的棧不是數(shù)據(jù)結(jié)構(gòu)中的棧,是JVM中的一個(gè)特定空間,對(duì)于 JVM 虛擬機(jī),這里存儲(chǔ)是 方法(我們自己寫的java代碼中的方法) 之間的調(diào)用關(guān)系.對(duì)于 本地方法棧,存儲(chǔ)的是JVM內(nèi)部方法的調(diào)用關(guān)系
整個(gè)??臻g內(nèi)部,可以認(rèn)為包含很多元素,每個(gè)元素表示一個(gè)方法. 這里的每個(gè)元素,稱為一個(gè)"棧幀",這一個(gè)棧幀里,會(huì)包含這個(gè)方法的 入口地址,方法的參數(shù)是什么,返回地址是什么,局部變量等
數(shù)據(jù)結(jié)構(gòu)的棧,是一個(gè)通用的更廣泛的概念,是后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),此處的JVM中的棧,特指JVM上的一塊內(nèi)存空間,由于函數(shù)調(diào)用,也是有后進(jìn)先出的特點(diǎn)
JVM中虛擬機(jī)中的棧,有很多,每一個(gè)線程都有一個(gè)屬于自己的棧,每一個(gè)棧都有很多的棧幀,調(diào)用一個(gè)方法會(huì)創(chuàng)建棧幀,方法結(jié)束,就會(huì)銷毀這個(gè)棧幀
JVM中的堆
堆是整個(gè) JVM 空間最大的區(qū)域,new 出來的對(duì)象(引用類型),都是在堆上.因此類的成員變量也在堆上.
堆是一個(gè)進(jìn)程只有一份,一個(gè)進(jìn)程中的多個(gè)線程共用一份堆.棧是一個(gè)線程有一個(gè)棧,一個(gè)進(jìn)程有N個(gè)棧
堆的生命周期比較長,堆上面的方法執(zhí)行結(jié)束默認(rèn)不自動(dòng)釋放空間,而棧上面的方法會(huì)隨著方法執(zhí)行結(jié)束,自動(dòng)釋放空間
程序計(jì)數(shù)器
記錄當(dāng)前線程執(zhí)行到哪個(gè)指令,每個(gè)線程都獨(dú)有一份程序計(jì)數(shù)器
方法區(qū)(元數(shù)據(jù)區(qū))
方法區(qū)每個(gè)進(jìn)程只有一個(gè),多個(gè)線程共用一份,? 類對(duì)象,常量池,靜態(tài)成員(static)都在方法區(qū)
給一段代碼,某個(gè)變量在哪個(gè)區(qū)域上?
原則
1.局部變量在 棧 上
2.普通成員變量在 堆 上
3.靜態(tài)成員變量在 方法區(qū)/元數(shù)據(jù)區(qū) 上
類加載
類加載: 類加載就是 .class文件,從文件(硬盤)被加載到內(nèi)存中(方法區(qū)/元數(shù)據(jù)區(qū))這樣的過程
加載: 把.class文件找到,打開文件,讀文件,把文件內(nèi)容讀到內(nèi)存中,最終得到類對(duì)象
驗(yàn)證: 檢查.class文件格式是否正確?
準(zhǔn)備: 給類對(duì)象分配一個(gè)內(nèi)存空間(在方法區(qū)/元數(shù)據(jù)區(qū)占個(gè)位置),會(huì)使靜態(tài)成員被設(shè)置成0值
解析: 初始化字符串常量,把符號(hào)引用轉(zhuǎn)換為直接引用
初始化: 調(diào)用構(gòu)造方法,進(jìn)行成員初始化,執(zhí)行代碼塊,靜態(tài)代碼塊,加載父類...? ? ??
類加載時(shí)機(jī)
java程序運(yùn)行,不是把所有的類都加載了,而是真正用到了才加載(懶漢模式),一旦加載過后,后續(xù)再使用就不必重復(fù)加載了
1.構(gòu)造類的實(shí)例
2.調(diào)用這個(gè)類的 靜態(tài)方法/使用靜態(tài)屬性
3.加載子類,就會(huì)先加載父類
雙親委派模型
雙親委派模型,描述的是 加載過程 找.class文件,基本過程
JVM默認(rèn)提供了 三個(gè) 類加載器
BootstrapClassLoader:? 負(fù)責(zé)加載標(biāo)準(zhǔn)庫中的類(java規(guī)范)
ExtensionClassLoader:? 負(fù)責(zé)加載JVM擴(kuò)展中的類(規(guī)范之外)
ApplicationClassLoader: 負(fù)責(zé)加載用戶提供的第三方庫/用戶項(xiàng)目代碼 中的類
上述三個(gè)類存在父子關(guān)系,BootstrapClassLoader是ExtensionClassLoader的父類,ExtensionClassLoader是ApplicationClassLoader的父類
加載一個(gè)類的時(shí)候是先從ApplicationClassLoader開始的,但是 ApplicationClassLoader會(huì)把加載任務(wù),交給父親,讓父親去執(zhí)行.于是ExtensionClassLoader要去加載,但是ExtensionClassLoader也會(huì)委托給自己的父親,于是BootstrapClassLoader就要去加載了,BootstrapClassLoader也想委托給自己的父類,可以它沒有父類,因此就由自己加載,此時(shí) Bootstrap就會(huì)搜索自己負(fù)責(zé)的標(biāo)準(zhǔn)庫目錄的相關(guān)的類,如果找到就加載,如果沒找到,就由子類加載器進(jìn)行加載..? ExtensionClassLoader 真正搜索擴(kuò)展庫相關(guān)的目錄,如果找到就加載,如果沒找到就由子類加載器加載.? ApplicationClassLoader,加載器進(jìn)行加載(由于當(dāng)前沒有子類,如果沒有找到,就會(huì)拋出 類找不到 這樣的異常)
GC 垃圾回收機(jī)制
垃圾指的是不再使用的內(nèi)存,垃圾回收,就是把不用的內(nèi)存幫我們自動(dòng)釋放掉了. 而GC 就是一種主流的垃圾回收機(jī)制,GC垃圾回收機(jī)制 主要是針對(duì) 堆 里面的空間進(jìn)行釋放的, GC 是以"對(duì)象" 為基本單位,進(jìn)行回收的
GC 實(shí)際工作過程
1.找到垃圾/判定垃圾
哪個(gè)對(duì)象是垃圾,哪個(gè)對(duì)象不是垃圾,哪個(gè)對(duì)象以后可能還要使用,哪個(gè)對(duì)象后面不用了,關(guān)鍵思路是:看這個(gè)對(duì)象,有沒有別的引用指向它(java中,使用對(duì)象只能通過引用來使用,如果一個(gè)對(duì)象沒有引用指向,那么它一定不被使用)
具體如何判斷對(duì)象是否有引用指向
1.可達(dá)性分析(Java中的做法)
Java 中的對(duì)象,都是通過引用來指向并訪問的,經(jīng)常是,一個(gè)引用指向一個(gè)對(duì)象,這個(gè)對(duì)象里的成員,又指向別的對(duì)象,比如鏈表,二叉樹
整個(gè)Java中所有的對(duì)象,通過鏈表/樹結(jié)構(gòu),整體串起來,可達(dá)性分析 就是把所有這些對(duì)象被組織的結(jié)構(gòu)稱為樹,從樹根節(jié)點(diǎn)出發(fā),所有能被訪問到的對(duì)象,標(biāo)記成 "可達(dá)",不能訪問到的,就是"不可達(dá)"
因此,通過上述標(biāo)記JVM就可以知道所有可達(dá)的對(duì)象,剩下的不可達(dá)對(duì)象,就視為垃圾 進(jìn)行回收
2.引用計(jì)數(shù)
給每個(gè)對(duì)象分配一個(gè)計(jì)數(shù)器(整數(shù)),每有一個(gè)引用指向該對(duì)象,計(jì)數(shù)器就+1,每次該引用被銷毀 計(jì)數(shù)器就-1,引用計(jì)數(shù)為0時(shí),此時(shí)這個(gè)對(duì)象就可以認(rèn)為是垃圾了
2.清理垃圾
1.標(biāo)記清除
直接把被標(biāo)記的垃圾清除掉,缺點(diǎn): 被釋放的空間是閑散,零散,不連續(xù),而我們申請(qǐng)內(nèi)存需要連續(xù)的內(nèi)存空間
2.復(fù)制算法
把不是垃圾的對(duì)象,復(fù)制到另一半,然后把剛剛有垃圾的一半整個(gè)空間刪除掉.解決了內(nèi)存碎片的問題
缺點(diǎn),空間利用率低,如果要是垃圾少,有效對(duì)象多,復(fù)制成本大
3.標(biāo)記整理
類似順序表刪除中間元素,把是垃圾的元素用不是垃圾的元素給填掉(元素搬運(yùn)),再釋放空間文章來源:http://www.zghlxwxcb.cn/news/detail-732246.html
分代回收(復(fù)制算法+標(biāo)記整理)
根據(jù)不同的場(chǎng)景,使用不同的算法
分代: 基于經(jīng)驗(yàn)規(guī)律,根據(jù)生命周期的長短,分別使用不同的算法
給對(duì)象引入一個(gè) 年齡 的概念,單位是 熬過GC垃圾回收的輪次,把年齡小的對(duì)象使用復(fù)制算法刪除(年齡小的對(duì)象中,可能是垃圾的比較多),把年齡大的對(duì)象使用標(biāo)記整理刪除(老年代對(duì)象可能是垃圾較少)文章來源地址http://www.zghlxwxcb.cn/news/detail-732246.html
到了這里,關(guān)于JVM基礎(chǔ)知識(shí)(內(nèi)存區(qū)域劃分,類加載,GC垃圾回收)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!