成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)

Loong_T / 2538人閱讀

摘要:運(yùn)行時(shí)數(shù)據(jù)區(qū)域之所以要?jiǎng)澐诌@么多區(qū)域出來(lái)是因?yàn)檫@些區(qū)域都有自己的用途,以及創(chuàng)建和銷(xiāo)毀的時(shí)間。,運(yùn)行時(shí)常量池它是方法區(qū)的一部分。直接內(nèi)存直接內(nèi)存并不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分,也不是虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域。

前言

說(shuō)到JAVA內(nèi)存區(qū)域,可能很多人第一反應(yīng)是“堆?!薄?br>首先,堆棧不是一個(gè)概念,而是兩個(gè)概念,堆和棧是兩塊不同的內(nèi)存區(qū)域,簡(jiǎn)單理解的話(huà),堆是用來(lái)存放對(duì)象而棧是用來(lái)運(yùn)行程序的。
其次,堆內(nèi)存和棧內(nèi)存的這種劃分方式比較粗糙,這種劃分方式只能說(shuō)明大多數(shù)程序員最關(guān)注的、與對(duì)象內(nèi)存分配關(guān)系最密切的內(nèi)存區(qū)域是這兩塊,Java內(nèi)存區(qū)域劃分實(shí)際上遠(yuǎn)比這復(fù)雜。
對(duì)于Java程序員來(lái)說(shuō),在虛擬機(jī)自動(dòng)內(nèi)存管理機(jī)制的幫助下,不再需要為每一個(gè)new操作去配對(duì)deleted/free代碼,不容易出現(xiàn)內(nèi)存泄漏和內(nèi)存溢出問(wèn)題。
但是,也正是因?yàn)镴ava把內(nèi)存控制權(quán)交給了虛擬機(jī),一旦出現(xiàn)內(nèi)存泄漏和內(nèi)存溢出的問(wèn)題,就難以排查,因此一個(gè)好的Java程序員應(yīng)該去了解虛擬機(jī)的內(nèi)存區(qū)域以及會(huì)引起內(nèi)存泄漏和內(nèi)存溢出的場(chǎng)景。

運(yùn)行時(shí)數(shù)據(jù)區(qū)域

之所以要?jiǎng)澐诌@么多區(qū)域出來(lái)是因?yàn)檫@些區(qū)域都有自己的用途,以及創(chuàng)建和銷(xiāo)毀的時(shí)間。有些區(qū)域隨著虛擬機(jī)進(jìn)程的啟動(dòng)而存在,有的區(qū)域則依賴(lài)用戶(hù)線(xiàn)程的啟動(dòng)和結(jié)束而銷(xiāo)毀和建立。

1.線(xiàn)程獨(dú)有的內(nèi)存區(qū)域
(1) PROGRAM COUNTER REGISTER,程序計(jì)數(shù)器
這塊內(nèi)存區(qū)域很小,它是當(dāng)前線(xiàn)程所執(zhí)行的字節(jié)碼的行號(hào)指示器,字節(jié)碼解釋器通過(guò)改變這個(gè)計(jì)數(shù)器的值來(lái)選取下一條需要執(zhí)行的字節(jié)碼指令。Java方法這個(gè)計(jì)數(shù)器才有值,如果執(zhí)行的是一個(gè)Native方法,那這個(gè)計(jì)數(shù)器是空的。

(2) JAVA STACK,虛擬機(jī)棧
生命周期和線(xiàn)程周期相同。每個(gè)方法執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀,用于存儲(chǔ)局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息,每一個(gè)方法從調(diào)用至執(zhí)行完畢的過(guò)程,就對(duì)應(yīng)一個(gè)棧幀在虛擬機(jī)棧中入棧到出棧的過(guò)程。棧的大小和具體JVM的實(shí)現(xiàn)有關(guān),通常在256K~756Kz之間。

(3) NATIVE METHOD STACK,方法棧
和虛擬機(jī)棧起的作用一樣,只不過(guò)方法棧為虛擬機(jī)使用到的Native方法服務(wù)。虛擬機(jī)規(guī)范并沒(méi)有對(duì)這個(gè)區(qū)域有什么強(qiáng)制規(guī)定,因此我們使用的HotSpot虛擬機(jī),就干脆沒(méi)有這塊區(qū)域了,它和虛擬機(jī)棧是一起的。

2.線(xiàn)程間共享的內(nèi)存區(qū)域

(1) HEAP,堆
大多數(shù)應(yīng)用,堆都是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊,它在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建,此內(nèi)存唯一目的就是存放對(duì)象實(shí)例。由于現(xiàn)在垃圾收集器采用的基本都是分代收集算法,所以堆還可以細(xì)分為新生代和老年代,再細(xì)致一點(diǎn)還有Eden區(qū)、From Survivor區(qū)、To Survivor區(qū)。

(2) METHOD AREA,方法區(qū)
這塊區(qū)域用于存儲(chǔ)虛擬機(jī)加載的類(lèi)信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù),虛擬機(jī)規(guī)范是把這塊區(qū)域描述為堆的一個(gè)邏輯部分的,但實(shí)際它應(yīng)該是要和堆區(qū)分開(kāi)的。從上面提到的分代收集算法的角度來(lái)看,HotSpot中,方法區(qū)≈永久代。不過(guò)JDK7之后,我們使用的HotSpot應(yīng)該就沒(méi)有永久代這個(gè)概念了,會(huì)采用Native Memory來(lái)實(shí)現(xiàn)方法區(qū)的規(guī)劃了。

(3) RUNTIME CONSTANT POOL,運(yùn)行時(shí)常量池
它是方法區(qū)的一部分。Class文件中除了有類(lèi)的版本信息、字段、方法、接口等描述信息外,還有一項(xiàng)信息就是常量池,用于存放編譯期間生成的各種字面量和符號(hào)引用,這部分內(nèi)容將在類(lèi)加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中,另外翻譯出來(lái)的直接引用也會(huì)存儲(chǔ)在這個(gè)區(qū)域中。

(在JVM中,類(lèi)從被加載到虛擬機(jī)內(nèi)存中開(kāi)始,到卸載出內(nèi)存為止,它的整個(gè)生命周期包括:加載、驗(yàn)證、準(zhǔn)備、解析、初始化、使用和卸載7個(gè)階段。而解析階段即是虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過(guò)程。

在Java中,一個(gè)java類(lèi)將會(huì)編譯成一個(gè)class文件。在編譯時(shí),java類(lèi)并不知道所引用的類(lèi)的實(shí)際地址,因此只能使用符號(hào)引用來(lái)代替。而解析階段即是虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過(guò)程,翻譯出來(lái)的直接引用也是存儲(chǔ)在方法區(qū)的運(yùn)行時(shí)常量池中。)

3.直接內(nèi)存
直接內(nèi)存并不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分,也不是Java虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域。但是這部分內(nèi)存也被頻繁地使用,而且也可能導(dǎo)致內(nèi)存溢出的問(wèn)題。JDK1.4中新增加了NIO,引入了一種基于通道與緩沖區(qū)的I/O方式,它可以使用Native函數(shù)庫(kù)直接分配堆外內(nèi)存,然后通過(guò)一個(gè)存儲(chǔ)在Java堆中的DirectByteBuffer對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作。這樣能在一些場(chǎng)景中顯著提高性能,因?yàn)楸苊饬嗽贘ava堆和Native堆中來(lái)回復(fù)制數(shù)據(jù)。顯然本機(jī)直接內(nèi)存的分配不會(huì)受到Java堆大小的限制,但是,既然是內(nèi)存,肯定還是會(huì)受到本機(jī)總內(nèi)存大小及處理器尋址空間的限制。

對(duì)象創(chuàng)建

我們來(lái)看一下在虛擬機(jī)層面上創(chuàng)建對(duì)象的步驟:
1.虛擬機(jī)遇到一條new指令,首先去檢查這個(gè)指令的參數(shù)能否在常量池中定位到一個(gè)類(lèi)的符號(hào)引用,并且檢查這個(gè)符號(hào)引用代表的類(lèi)是否已經(jīng)被加載、解析和初始化。如果沒(méi)有,那么必須執(zhí)行類(lèi)的初始化過(guò)程。

2.類(lèi)加載檢查通過(guò)后,虛擬機(jī)為新生對(duì)象分配內(nèi)存。對(duì)象所需內(nèi)存大小在類(lèi)加載完成后便可以完全確定,為對(duì)象分配空間無(wú)非是從Java堆中劃分出一個(gè)確定大小的內(nèi)存而已。這個(gè)地方會(huì)有兩個(gè)問(wèn)題:
(1) 如果內(nèi)存是規(guī)整的,那么虛擬機(jī)將采用的是指針碰撞法來(lái)為對(duì)象分配內(nèi)存。意思是所有用過(guò)的內(nèi)存在一邊,空閑的內(nèi)存在另一邊,中間放著一個(gè)指針作為分界點(diǎn)指示器,分配內(nèi)存就僅僅是把指針向空閑那邊挪動(dòng)一段與對(duì)象大小相等的距離罷了。如果垃圾收集器選擇的是Serial、ParNew這種基于壓縮算法的,虛擬機(jī)采用這種分配方式。
(2) 如果內(nèi)存不是規(guī)整的,已使用的內(nèi)存和未使用的內(nèi)存相互交錯(cuò),那么虛擬機(jī)將采用的是空閑列表法來(lái)為對(duì)象分配內(nèi)存。意思是虛擬機(jī)維護(hù)了一個(gè)列表記錄了哪些內(nèi)存是可用的,再分配的時(shí)候從列表中找到一塊足夠大的空間劃分給實(shí)例,并更新列表上的內(nèi)容。如果垃圾收集器選擇是CMS這種基于標(biāo)記-清除(Mark-Sweep)算法的,虛擬機(jī)采用這種分配方式。
簡(jiǎn)言之,
垃圾收集器選擇的是Serial、ParNew這種基于Compact(壓縮)算法的,虛擬機(jī)采用指針碰撞法為對(duì)象分配內(nèi)存;
垃圾收集器選擇是CMS這種基于Mark-Sweep(標(biāo)記-清除)算法的,虛擬機(jī)采用空閑列表法為對(duì)象分配內(nèi)存。
另外一個(gè)問(wèn)題即是保證new對(duì)象時(shí)候的線(xiàn)程安全。因?yàn)榭赡艹霈F(xiàn)虛擬機(jī)正在給對(duì)象A分配內(nèi)存,指針還沒(méi)有來(lái)得及修改,對(duì)象B又同時(shí)使用了原來(lái)的指針來(lái)分配內(nèi)存的情況。虛擬機(jī)采用了CAS配上失敗重試和TLAB兩種方式保證更新操作的原子性來(lái)解決這個(gè)問(wèn)題。
(每個(gè)線(xiàn)程在Java堆中預(yù)先分配一小塊內(nèi)存,成為本地線(xiàn)程分配緩沖區(qū)——TLAB,線(xiàn)程內(nèi)部需要分配內(nèi)存時(shí)直接在TLAB上分配就行,避免了線(xiàn)程沖突。只有當(dāng)緩沖區(qū)的內(nèi)存用光需要重新分配內(nèi)存的時(shí)候才會(huì)進(jìn)行CAS操作分配更大的內(nèi)存空間。虛擬機(jī)是否使用TLAB,可以通過(guò)-XX:+/-UseTLAB參數(shù)來(lái)進(jìn)行配置,但是JDK5及以后的版本默認(rèn)是啟用TLAB的)

3.內(nèi)存分配結(jié)束,虛擬機(jī)講分配到的內(nèi)存空間都初始化為零值(不包括對(duì)象頭)。這一步保證了對(duì)象的實(shí)例字段在Java代碼中可以不用賦初始值就可以直接使用,程序能訪(fǎng)問(wèn)到這些字段的數(shù)據(jù)類(lèi)型所對(duì)應(yīng)的零值。

4.對(duì)對(duì)象進(jìn)行必要的配置,例如這個(gè)對(duì)象是哪個(gè)類(lèi)的實(shí)例、如何才能找到類(lèi)的元數(shù)據(jù)信息、對(duì)象的哈希嗎、對(duì)象的GC分代年齡等信息,這些信息存放在對(duì)象的對(duì)象頭中。

5.執(zhí)行方法,把對(duì)象按照程序員的意愿進(jìn)行初始化,這樣一個(gè)真正可用的對(duì)象才算完全產(chǎn)生出來(lái)。

對(duì)象定位方式

建立對(duì)象是為了使用對(duì)象,我們的Java程序需要通過(guò)棧上的reference數(shù)據(jù)來(lái)操作對(duì)上的具體對(duì)象。
比如,Object obj = new Object();而new Object()之后其實(shí)有兩部分內(nèi)容:一部分是類(lèi)數(shù)據(jù)(方法區(qū))、一部分是實(shí)例數(shù)據(jù)(堆)。
由于reference類(lèi)型在Java虛擬機(jī)規(guī)范里面只規(guī)定了是一個(gè)指向?qū)ο蟮囊?,并沒(méi)有定義這個(gè)引用應(yīng)該通過(guò)什么方式去定位、訪(fǎng)問(wèn)到堆中的對(duì)象的具體位置,對(duì)象訪(fǎng)問(wèn)方式也是取決于虛擬機(jī)實(shí)現(xiàn)而定的。主流的訪(fǎng)問(wèn)方式有使用句柄和直接指針兩種。

1.使用句柄

在Java堆中將會(huì)劃分出一塊內(nèi)存來(lái)作為句柄池,reference中存儲(chǔ)的就是對(duì)象的句柄地址,而句柄中包含了對(duì)象實(shí)例與類(lèi)型數(shù)據(jù)的具體各自的地址信息,

2.使用直接指針

使用直接指針訪(fǎng)問(wèn)的話(huà),Java堆對(duì)象的布局中就必須考慮如何放置訪(fǎng)問(wèn)類(lèi)型數(shù)據(jù)的相關(guān)信息,reference中存儲(chǔ)的直接就是對(duì)象地址,

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69081.html

相關(guān)文章

  • 對(duì)于JVM,你就只知道堆和棧嗎?

    摘要:下面的截圖內(nèi)容來(lái)自從規(guī)范我們可以看到,規(guī)范要求的運(yùn)行時(shí)數(shù)據(jù)區(qū)域有程序計(jì)數(shù)器虛擬機(jī)棧堆方法區(qū)本地方法棧運(yùn)行時(shí)常量池這及部分。查了一下,還是沒(méi)有查到官方對(duì)于運(yùn)行時(shí)數(shù)據(jù)區(qū)域的說(shuō)明,但是許多博客都指出將字符串常量池移動(dòng)到了堆中。 不少java程序員一提JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域,就會(huì)說(shuō)堆和棧,當(dāng)然也有java程序員給出方法區(qū)、虛擬機(jī)棧、本地方法棧、堆、程序計(jì)數(shù)器這個(gè)答案,但是還有人給出永久代、虛擬機(jī)...

    王笑朝 評(píng)論0 收藏0
  • 【譯】JVM框架說(shuō)明

    摘要:框架說(shuō)明開(kāi)發(fā)者都知道會(huì)執(zhí)行字節(jié)碼。但是可能大多數(shù)人都不知道一個(gè)事實(shí)是的實(shí)現(xiàn),它分析字節(jié)碼,解釋并執(zhí)行代碼。執(zhí)行引擎字節(jié)碼加載到運(yùn)行時(shí)數(shù)據(jù)區(qū)后,會(huì)被執(zhí)行引擎執(zhí)行。解釋器更快的解釋字節(jié)碼,但是執(zhí)行非常慢。垃圾收集收集并移除不再被使用的對(duì)象。 JVM框架說(shuō)明 java開(kāi)發(fā)者都知道JRE(Java Runtime Environment)會(huì)執(zhí)行字節(jié)碼。但是可能大多數(shù)人都不知道一個(gè)事實(shí):JRE是...

    tracymac7 評(píng)論0 收藏0
  • 一文了解JVM

    摘要:而使用虛擬機(jī)是實(shí)現(xiàn)這一特點(diǎn)的關(guān)鍵。每個(gè)字節(jié)碼指令都由一個(gè)字節(jié)的操作碼和附加的操作數(shù)組成。字節(jié)碼可以通過(guò)以下兩種方式轉(zhuǎn)換成合適的語(yǔ)言解釋器一條一條地讀取,解釋并執(zhí)行字節(jié)碼執(zhí)行,所以它可以很快地解釋字節(jié)碼,但是執(zhí)行起來(lái)會(huì)比較慢。 一、什么是JVM JVM是Java Virtual Machine(Java 虛擬機(jī))的縮寫(xiě),JVM是一種用于計(jì)算設(shè)備的規(guī)范,它是一個(gè)虛構(gòu)出來(lái)的計(jì)算機(jī),是通過(guò)在實(shí)...

    whatsns 評(píng)論0 收藏0
  • Java GC

    摘要:對(duì)字節(jié)碼文件進(jìn)行解釋執(zhí)行,把字節(jié)碼翻譯成相關(guān)平臺(tái)上的機(jī)器指令。使用命令可對(duì)字節(jié)碼文件以及配置文件進(jìn)行打包可對(duì)一個(gè)由多個(gè)字節(jié)碼文件和配置文件等資源文件構(gòu)成的項(xiàng)目進(jìn)行打包。和不存在永久代這種說(shuō)法。 Java技術(shù)體系 從廣義上講,Clojure、JRuby、Groovy等運(yùn)行于Java虛擬機(jī)上的語(yǔ)言及其相關(guān)的程序都屬于Java技術(shù)體系中的一員。如果僅從傳統(tǒng)意義上來(lái)看,Sun官方所定義的Jav...

    justCoding 評(píng)論0 收藏0
  • 萬(wàn)萬(wàn)沒(méi)想到,JVM內(nèi)存結(jié)構(gòu)的面試題可以問(wèn)的這么難?

    摘要:方法區(qū)在實(shí)際內(nèi)存空間站可以是不連續(xù)的。這一規(guī)定,可以說(shuō)是給了虛擬機(jī)廠商很大的自由。但是值得注意的是,堆其實(shí)還未每一個(gè)線(xiàn)程單獨(dú)分配了一塊空間,這部分空間在分配時(shí)是線(xiàn)程獨(dú)享的,在使用時(shí)是線(xiàn)程共享的。 在我的博客中,之前有很多文章介紹過(guò)JVM內(nèi)存結(jié)構(gòu),相信很多看多我文章的朋友對(duì)這部分知識(shí)都有一定的了解了。 那么,請(qǐng)大家嘗試著回答一下以下問(wèn)題: 1、JVM管理的內(nèi)存結(jié)構(gòu)是怎樣的? 2、不同的...

    CloudwiseAPM 評(píng)論0 收藏0
  • Java程序員:不識(shí)Jvm真面目,只緣身在增刪查改中

    摘要:編譯器只需面向,生成能理解的代碼或字節(jié)碼文件。源文件經(jīng)編譯器,編譯成字節(jié)碼程序,通過(guò)將每一條指令翻譯成不同平臺(tái)機(jī)器碼,通過(guò)特定平臺(tái)運(yùn)行。漲見(jiàn)識(shí),字節(jié)碼執(zhí)行過(guò)程分析。解決辦法減少默認(rèn)棧的容量來(lái)?yè)Q取更多的線(xiàn)程支持。 前言 JVM是java的核心和基礎(chǔ),在java編譯器和os平臺(tái)之間的虛擬處理器。它是一種基于下層的操作系統(tǒng)和硬件平臺(tái)并利用軟件方法來(lái)實(shí)現(xiàn)的抽象的計(jì)算機(jī),可以在上面執(zhí)行java的...

    or0fun 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<