重慶付費網(wǎng)站推廣友情鏈接交換工具
目錄
1.JVM運行時數(shù)據(jù)區(qū)
2.JVM類加載過程
3.雙清委派模型
4.垃圾回收機(jī)制(GC)
找出誰是垃圾方案一:引用計數(shù)
找出誰是垃圾:方案二,可達(dá)性分析
釋放垃圾的內(nèi)存空間
判斷垃圾:jvm依據(jù)對象的年齡對 對象進(jìn)行區(qū)域劃分。
回收垃圾方式:分代回收
1.JVM運行時數(shù)據(jù)區(qū)
JVM運行時數(shù)據(jù)區(qū)域 也叫做:JVM內(nèi)存布局。
JVM內(nèi)存布局 和 java內(nèi)存模型完全不同,JVM內(nèi)存布局由5大部分組成。
1.堆區(qū)(線程共享):程序中所有創(chuàng)建的對象都保存在堆中。JVM最大空間。
2.棧(線程私有):
????????1>.java虛擬機(jī)棧作用(線程私有):Java虛擬機(jī)棧的生命周期 和 線程相同,Java虛擬機(jī)棧描述了java方法執(zhí)行的內(nèi)存模型:每個方法在執(zhí)行時 都會創(chuàng)建一個棧幀,用來儲存局部變量,方法之間的調(diào)用關(guān)系,動態(tài)鏈接,方法出口等等。
? ? ? ? 2>.本地方法棧:與虛擬機(jī)棧類似,只不過是給本地方法使用的,本地方法由C++代碼編寫。
3.程序計數(shù)器(線程私有):保存下一條要執(zhí)行的指令的地址。這里不是CPU寄存器儲存的,而是內(nèi)存空間,指令是java的字節(jié)碼。不是二進(jìn)制機(jī)器語言。
4.元數(shù)據(jù)區(qū):(以前叫方法區(qū))保存java代碼中涉及類的相關(guān)信息。類的static屬性。
在一個java進(jìn)程中,元數(shù)據(jù)區(qū) 和 堆 是只有一份的。即同一個進(jìn)程中的所有線程共用一份數(shù)據(jù)。
一個java進(jìn)程中有多個線程,多個線程都有自己的 程序計數(shù)器 和 棧。所以每個線程都需要保存自己的“程序計數(shù)器” 每個線程都需要記錄自己的 調(diào)用關(guān)系。
檢測一下是掌握的怎么樣,下面代碼中的變量都儲存在哪些區(qū)域?
public class test4 {static class Test{private int a;private Test b = new Test();private static int c;private static Test d = new Test();}public static void main(String[] args) {int e = 10;Test f = new Test();}
}
一般地:
局部變量:棧
成員變量:堆
靜態(tài)成員變量:元數(shù)據(jù)區(qū)(方法區(qū))
2.JVM類加載過程
一個類的生命周期大致為下幾個過程。
編寫一個java程序 會得到一個 .java文件,在經(jīng)過javac 編譯 就會得到一個 .class文件。
想要運行java 進(jìn)程,jvm就需要 讀取 .class 文件并執(zhí)行里面的指令。
jvm讀取到 .class里面的內(nèi)容 這個就是類加載。把類 涉及的字節(jié)碼,從硬盤讀取到 內(nèi)存里。
?加載一個 .claas文件,就會對應(yīng)創(chuàng)建一個類對象。類對象包含了.class
文件里的各種信息。
類名字,類的屬性,類有哪些方法,繼承的父類有哪些,實現(xiàn)的接口有哪些....
具體步驟:
1.加載:把 .class 文件找到,然后打開并讀取文件的內(nèi)容。
代碼中先見到 類的名字,然后進(jìn)一步找到對應(yīng)的 .class 文件(涉及一系列的目錄查找過程)
2.驗證:驗證讀到的 .class 文件的數(shù)據(jù)是否正確,是否合法。
java標(biāo)準(zhǔn)文檔中明確規(guī)定 .class 文件的格式是怎么樣的。
3.準(zhǔn)備:分配內(nèi)存空間。
根據(jù)讀取到的內(nèi)容大小,確定出類對象需要的內(nèi)存空間,申請這樣大小的空間,并把這個空間全部初始化為0.
4.解析:主要針對類中的字符串常量進(jìn)行處理
java虛擬機(jī) 將字符串常量池中的 符號引用 替換為直接引用的過程,也就是初始化常量。
符號引用 其實就是指(字符串常量已經(jīng)在 .class文件中)文件中 符號的位置,就是偏移量。
直接引用 就是直接保存變量的地址。
5.初始化:針對 類對象 做最終的初始化操作,執(zhí)行靜態(tài)成員賦值語句。
3.雙清委派模型
操作: 輸入一個 類的全限定名(類似于java.lang.String),的到對應(yīng)的 .class 文件。
屬于 jvm加載類中的第一個機(jī)制:加載
Bootstrap ClassLoader(加載 標(biāo)準(zhǔn)庫中的類)
ExtensionClassLoader(加載 擴(kuò)展庫的類)
ApplicationClassLoader(負(fù)責(zé)加載第三方庫的類)
?
為什么會是這個流程?
核心目的是 方式用戶自己寫的類把?標(biāo)準(zhǔn)庫 或者 擴(kuò)展庫給覆蓋掉。
保證 標(biāo)準(zhǔn)庫的類是第一位,擴(kuò)展庫的類的是第二位。最后是第三方庫的類。
防止程序員 不小心創(chuàng)建一個 和 系統(tǒng)中已有的類重名的類。導(dǎo)致加載的時候覆蓋掉了系統(tǒng)的類。
4.垃圾回收機(jī)制(GC)
GC 主要存在哪里呢?
棧 和 程序計數(shù)器 主要都是跟隨線程的結(jié)束而結(jié)束。
元數(shù)據(jù)區(qū):類對象涉及到的類加載,一個程序里面嗎要加載得類都是有上限的,不會出現(xiàn)無限增長的情況。
所以 堆是GC得主要戰(zhàn)區(qū)。
垃圾回收,回收內(nèi)存 都是一對象為維度進(jìn)行回收的。
GC回收的流程:1.找出誰是垃圾???????? 2.釋放垃圾的內(nèi)存空間
找出誰是垃圾方案一:引用計數(shù)
給每個對象分配一個計數(shù)器,衡量有多少個引用指向。
每增加一個引用,計數(shù)器+1
每減少一個引用,計數(shù)器-1,如果計數(shù)器為0,此對象就垃圾了需要回收。
此時 對象中的計數(shù)器為0,就視為垃圾,需要回收。
上述方案存在兩個問題:
1.消耗額外空間去 儲存計數(shù)器
假設(shè)Tets類,只有一個int(4字節(jié))成員,那么就要花2個字節(jié)儲存計數(shù)器,內(nèi)存多用了 50%
2.引用計數(shù)可能會導(dǎo)致“循環(huán)引用”,使得上述判定出錯。
這種情況就是最后 這倆對象計數(shù)器都不是0,都不能被釋放。
找出誰是垃圾:方案二,可達(dá)性分析
用時間換取空間。
JVM中專門搞了一波周期性的線程,掃面代碼中的所有對象,判定某個對象是否“可達(dá)”。
對應(yīng)的,不可達(dá)的就是垃圾。
JVM中有所有對象的總名單,按照名單點名,如果沒有到的 ,就是垃圾。
JVM中有很多的root根,從這個root開始可以把所有的對象都遍歷到。遍歷不到但是名單上存在就是垃圾。
釋放垃圾的內(nèi)存空間
1.標(biāo)記-清除法
如果直接對內(nèi)存空間進(jìn)行標(biāo)記清楚,就有可能導(dǎo)致碎片化的空間無法充分利用。
這樣剩下的三個空間就不容易利用了,碎片化的空間不能進(jìn)行申請連續(xù)的空間。
2.復(fù)制算法
將被回收后的空間的一分為二,把不是垃圾的對象拷貝到另一側(cè)。確?;厥蘸蟮玫竭B續(xù)的空間
這個算法缺點很明顯:
1.內(nèi)存空間利用率低
2.如果存活下來的對象比較多,復(fù)制成本也很大。
3.標(biāo)記-整理
與標(biāo)記-清楚類似,但是不一樣的是后續(xù)并不是直接回收對象,而是讓所有的存活對象都向前移動,最后直接清理掉邊界標(biāo)記的就可以了。
4.jvm中真正的解決方案。
判斷垃圾:jvm依據(jù)對象的年齡對 對象進(jìn)行區(qū)域劃分。
如果獲得年齡,使用可達(dá)性分析 對對象進(jìn)行掃描,每次描掃后對象的年齡就+1
1.伊甸區(qū)比較大,讓新創(chuàng)建的對象存放,大多數(shù)新創(chuàng)建的對象都活不過第一輪GC,留下來的對象拷貝到幸存區(qū)。
2.幸存區(qū),是兩個相按照復(fù)制算法將存活久對象復(fù)制到幸存區(qū),反復(fù)多次。幸存區(qū)里也會為了保留完整空間進(jìn)行左右多次復(fù)制。
3.一個對象在幸存區(qū)多次被拷貝,年齡不斷增長,就要拷貝到老年代了。
4.根據(jù)經(jīng)驗規(guī)律,老年代的對象生命周期都比較長,即便如此也是要進(jìn)行可達(dá)性分析的。
但是老年代的GC頻率較低。老年代也需要通過標(biāo)記整理。
回收垃圾方式:分代回收
分代回收時JVM的GC基本思想方法。
jvm還提供許多“垃圾回收器”對上述的分代回收 作進(jìn)一步的擴(kuò)充和具體實現(xiàn)。
CMS涉及理念,把整個GC過程拆分成多個階段,能和業(yè)務(wù)線程并發(fā)運行的。就盡量并發(fā)減少STW時間。
G1把整個內(nèi)存分成很多快,不同的顏色表示這個一塊區(qū)域是哪一塊(新生代,老年代,幸存區(qū)...)
進(jìn)行GC時不要求一周期就把多個內(nèi)存都回收,只要回收一部分就好。限制一輪GC的工作量,目的是使STW控制在一定范圍,降低STW的影響。