Java堆是jvm內(nèi)存中被所有線程共享的一塊區(qū)域,該區(qū)域物理上可以不連續(xù)但是邏輯上連續(xù)即可。Java堆存放著程序運(yùn)行中生成的對(duì)象實(shí)例數(shù)據(jù)。在jdk1.7及以上版本,Hotspot虛擬機(jī)將運(yùn)行時(shí)常量池和靜態(tài)變量從方法區(qū)中移到了Java堆中。每個(gè)對(duì)象在Java堆上分配內(nèi)存時(shí),并發(fā)場(chǎng)景下,虛擬機(jī)采用CAS自旋鎖和TLAB的方式保證內(nèi)存的安全分配。具體分配方式根據(jù)不同垃圾收集器大體上分為指針碰撞和空閑列表兩種。基于對(duì)象垃圾回收的強(qiáng)弱分代假說,即大多數(shù)對(duì)象是朝生夕死的,熬過越多次垃圾回收的對(duì)象越不容易消亡;主流虛擬機(jī)將Java堆劃分為新生代和老年代,默認(rèn)比例1:2,可以通過jvm參數(shù)修改。其中新生代中又具體劃分為一個(gè)Eden區(qū)和兩個(gè)Survivor區(qū),默認(rèn)比例8:1:1,可以通過jvm參數(shù)修改。堆內(nèi)存的大小也可以通過jvm參數(shù)指定。垃圾收集器主要就是收集堆中的數(shù)據(jù),經(jīng)過垃圾回收后仍然無法給新對(duì)象分配內(nèi)存時(shí),此區(qū)域會(huì)觸發(fā)OOM錯(cuò)誤。
成都創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括巴彥淖爾網(wǎng)站建設(shè)、巴彥淖爾網(wǎng)站制作、巴彥淖爾網(wǎng)頁制作以及巴彥淖爾網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,巴彥淖爾網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到巴彥淖爾省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!2.虛擬機(jī)棧虛擬機(jī)棧是jvm內(nèi)存中線程私有的一塊區(qū)域,它與線程的生命周期相同。虛擬機(jī)棧的存儲(chǔ)單位是棧幀,每個(gè)方法的執(zhí)行和結(jié)束代表著一個(gè)棧幀的入棧和出棧。每個(gè)棧幀中存儲(chǔ)著局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法返回地址和一些附加信息。棧內(nèi)存大小決定了方法調(diào)用的深度,方法調(diào)用深度過大,如遞歸調(diào)用時(shí),容易引發(fā)StackOverflow錯(cuò)誤,一個(gè)線程的創(chuàng)建就會(huì)伴隨著創(chuàng)建一個(gè)虛擬機(jī)棧,而創(chuàng)建線程也會(huì)占用jvm內(nèi)存,當(dāng)jvm無法為新線程分配內(nèi)存時(shí),此區(qū)域也會(huì)引發(fā)OOM錯(cuò)誤。虛擬機(jī)棧的大小可以通過jvm參數(shù)指定。
3.本地方法棧本地方法棧與虛擬機(jī)棧類似,也是屬于線程私有的一塊區(qū)域。只不過本地方法棧是jvm執(zhí)行的native方法,native方法是jdk環(huán)境提供的本地方法,由c或c++語言實(shí)現(xiàn)。此區(qū)域同樣會(huì)有StackOverflow和OOM的風(fēng)險(xiǎn)。
4.方法區(qū)方法區(qū)是jvm虛擬機(jī)的設(shè)計(jì)規(guī)范,其具體實(shí)現(xiàn)為永久代和元空間,此區(qū)域是所有線程共享的一塊區(qū)域。在jdk1.6及以前,Hotspot虛擬機(jī)采用永久代的方式實(shí)現(xiàn)方法區(qū)。可以通過jvm參數(shù)設(shè)置永久代的大小。永久代中主要存放著類的Class字節(jié)碼信息、靜態(tài)變量、運(yùn)行時(shí)常量池和JIT即時(shí)編譯器編譯后的代碼,由于這些數(shù)據(jù)在程序運(yùn)行中被回收的概率很小,但是卻占據(jù)著寶貴的jvm內(nèi)存,在一些熱部署的場(chǎng)景下,加載大量類信息,很容易引發(fā)此區(qū)域OOM,然而這些風(fēng)險(xiǎn)在系統(tǒng)的正常運(yùn)行中不易發(fā)現(xiàn)。所以從jdk1.7開始,考慮將永久代從jvm內(nèi)存中移除,直接使用操作系統(tǒng)內(nèi)存存儲(chǔ)這些信息。jdk1.7時(shí),已經(jīng)將運(yùn)行時(shí)常量池、靜態(tài)變量從永久代中轉(zhuǎn)移到堆中存儲(chǔ)。到j(luò)dk1.8時(shí),Hotspot虛擬機(jī)徹底將永久代從jvm內(nèi)存中移除,轉(zhuǎn)而使用MetaSpace代替永久代,metaSpace使用的是操作系統(tǒng)和的內(nèi)存。因此不會(huì)再出現(xiàn)OOM的錯(cuò)誤。(除非超過了操作系統(tǒng)的內(nèi)存)。
5.運(yùn)行時(shí)常量池運(yùn)行時(shí)常量池是程序運(yùn)行中儲(chǔ)存Class對(duì)象的常量信息,包括字面量和符號(hào)引用。一個(gè)Class文件對(duì)應(yīng)一個(gè)Class常量池,在程序運(yùn)行時(shí),Class文件被加載到j(luò)vm內(nèi)存中時(shí),就會(huì)產(chǎn)生一個(gè)Class運(yùn)行時(shí)常量池。在jdk1.6及以前,每個(gè)Class的運(yùn)行時(shí)常量池中還存在一份字符串常量池,多個(gè)Class運(yùn)行時(shí)常量池中就會(huì)存在多份字符串常量池,而這些字符串常量池中的常量有很多是重復(fù)的,所以浪費(fèi)了很大的內(nèi)存空間,于是jdk從1.7開始,將字符串常量池從每個(gè)Class運(yùn)行時(shí)常量池中移出來,統(tǒng)一成一份存儲(chǔ)在堆空間中。避免了內(nèi)存空間的浪費(fèi)。
6.直接內(nèi)存直接內(nèi)存并不是Java虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域。jdk1.4時(shí)引入了NIO網(wǎng)絡(luò)傳輸模型,它可以通過native函數(shù)庫直接分配堆外內(nèi)存,因?yàn)楸苊饬薐ava堆和native堆來回復(fù)制數(shù)據(jù)的操作,在頻繁進(jìn)行IO操作的場(chǎng)景下性能顯著提高,直接內(nèi)存與Java堆內(nèi)存相比,因?yàn)闊o法利用Java堆分配內(nèi)存的優(yōu)良特性,并發(fā)場(chǎng)景下申請(qǐng)直接內(nèi)存更耗費(fèi)性能,但是直接內(nèi)存在頻繁IO操作的場(chǎng)景下性能要由于Java堆內(nèi)存。
7.為什么堆內(nèi)存要分年輕代和老年代?堆內(nèi)存好比是一塊收納空間,如果沒有合理的規(guī)劃空間的劃分,很容易造成頻繁使用的東西難以找到,經(jīng)常不用的東西隨處可見,而且東西亂丟亂放也很容易造成空間資源的浪費(fèi)。基于垃圾回收的強(qiáng)弱分代假說,大多數(shù)對(duì)象都是朝生夕死的,堅(jiān)持越久不被回收的對(duì)象越不容易消亡,所以將堆內(nèi)存劃分為年輕代和老年代,目的就是將朝生夕死的對(duì)象和持續(xù)不死的對(duì)象劃分開,從而提升垃圾回收的效率。
8.一個(gè)對(duì)象的創(chuàng)建過程jvm識(shí)別到new指令時(shí),會(huì)先檢查指令的參數(shù)是否在運(yùn)行時(shí)常量池中能定位到這個(gè)類的符號(hào)引用,并檢查符號(hào)引用代表的類是否已經(jīng)被加載過,解析和初始化過,如果沒有,則會(huì)先執(zhí)行相應(yīng)的類加載過程,如果有,則會(huì)開始為該對(duì)象在堆空間分配內(nèi)存。jvm將分配到的內(nèi)存都初始化為零值,緊接著為對(duì)象設(shè)置對(duì)象頭信息,包括類元數(shù)據(jù)信息、哈希值、GC分代年齡等。接下來會(huì)執(zhí)行init方法,按照開發(fā)者意愿給對(duì)象中的變量賦值。至此,對(duì)象創(chuàng)建完畢。
9.一個(gè)對(duì)象的內(nèi)存分配對(duì)象在堆空間上分配內(nèi)存,不同的垃圾收集器采用的方式有所不同,主要分為指針碰撞和空閑列表兩種分配方式。如果堆內(nèi)存是規(guī)整的,所有已使用的內(nèi)存放到一邊,空閑的放到另一邊,中間維護(hù)一個(gè)指針作為分界點(diǎn),當(dāng)為新對(duì)象分配內(nèi)存時(shí),只需要把指針向空閑方向移動(dòng)一段與新對(duì)象大小相等的實(shí)例,這種分配方式稱為指針碰撞。如果堆內(nèi)存是不規(guī)整的,jvm必須維護(hù)一個(gè)列表,記錄哪些內(nèi)存可以使用,在分配內(nèi)存時(shí),需要在列表中找到一塊空間分配給對(duì)象,然后更新列表上的記錄,這種分配方式稱為空閑列表。對(duì)象在堆中分配內(nèi)存時(shí)及其頻繁的操作,為了解決線程安全的問題,jvm采取TLAB的方式,每個(gè)線程在堆中預(yù)先分配一小塊內(nèi)存,若TLAB分配內(nèi)存失敗,jvm會(huì)采取CAS自旋鎖的方式直接在堆中分配內(nèi)存,保障內(nèi)存分配時(shí)的線程安全。
新對(duì)象大多數(shù)會(huì)在新生代的Eden區(qū)分配到內(nèi)存,當(dāng)新對(duì)象很大,Eden分配失敗時(shí),YoungGC觸發(fā)前,首先會(huì)進(jìn)行老年代空間擔(dān)保判斷,若老年代的可用內(nèi)存小于新生代所有存活對(duì)象占用的內(nèi)存大小,會(huì)再次判斷老年代的可用內(nèi)存是否小于之前YoungGC后新生代對(duì)象進(jìn)入老年代的平均大小,如果小于,直接觸發(fā)FullGC,F(xiàn)ullGC后若新對(duì)象能夠成功分配內(nèi)存,則直接在老年代中分配內(nèi)存,若分配失敗,報(bào)OOM錯(cuò)誤;如果大于,首先會(huì)觸發(fā)一次YoungGC,YoungGC后,新生代中存活的對(duì)象小于老年代可用內(nèi)存的前提下,會(huì)將新生代中的存活對(duì)象年齡默認(rèn)超過15直接進(jìn)入到老年代;Survivor區(qū)中的存活對(duì)象大小超過了該區(qū)域的50%時(shí),會(huì)將大于等于這批存活對(duì)象年齡大值的所有對(duì)象直接進(jìn)入到老年代;若新生代中存活對(duì)象大小超過Survivor區(qū),也會(huì)直接進(jìn)入到老年代。如果YoungGC后,新生代中存活的對(duì)象大小超過老年代可用內(nèi)存,會(huì)再次觸發(fā)FullGC,F(xiàn)ullGC后繼續(xù)將新生代存活對(duì)象進(jìn)入到老年代,失敗報(bào)OOM,新生代對(duì)象進(jìn)入老年代成功后,在老年代為新對(duì)象直接分配內(nèi)存,失敗報(bào)OOM。
10.一個(gè)對(duì)象的銷毀過程待補(bǔ)充
11.對(duì)象的兩種訪問方式待補(bǔ)充
12.為什么需要內(nèi)存擔(dān)保?待補(bǔ)充
13.垃圾收集算法有哪些?垃圾收集器有哪些?他們的特點(diǎn)是什么?待補(bǔ)充
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)站欄目:JVM相關(guān)知識(shí)點(diǎn)-創(chuàng)新互聯(lián)
URL分享:http://m.newbst.com/article48/dcgohp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、面包屑導(dǎo)航、網(wǎng)站維護(hù)、外貿(mào)建站、域名注冊(cè)、App設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容