国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【JVM從小白學(xué)成大佬】2.Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)

shuibo / 3628人閱讀

摘要:虛擬機(jī)在執(zhí)行程序的過程中會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。棧幀棧幀是用于支持虛擬機(jī)進(jìn)行方法調(diào)用和方法執(zhí)行的數(shù)據(jù)結(jié)構(gòu),它是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)中的虛擬機(jī)棧的棧元素。棧幀的概念結(jié)構(gòu)如下運(yùn)行時(shí)數(shù)據(jù)區(qū)腦圖高

這里我們先說句題外話,相信大家在面試中經(jīng)常被問到介紹Java內(nèi)存模型,我在面試別人時(shí)也會(huì)經(jīng)常問這個(gè)問題。但是,往往都會(huì)令我比較尷尬,我還話音未落,面試者就會(huì)“背誦”一段(Java虛擬機(jī)時(shí)有堆、方法去、虛擬機(jī)棧,吧啦吧啦。。。),估計(jì)心里還一臉自豪的想幸好哥提前在網(wǎng)上搜過,早有準(zhǔn)備。每每這個(gè)時(shí)候,我都不忍心打斷,因?yàn)椤氨痴b”的真的太順暢了!

這也怪不得面試者,首先Java虛擬機(jī)方面的知識(shí),對中高級(jí)程序猿來說,工作中正面接觸Java虛擬機(jī)的東西不多。其次,這個(gè)其次咱得好好嘮嘮,網(wǎng)上搜個(gè)Java內(nèi)存模型,度娘推的第一頁大都是介紹Java運(yùn)行時(shí)數(shù)據(jù)區(qū)的,起到了一定的誤導(dǎo)作用,大寫的尷尬。

本篇將給各位小伙伴先詳細(xì)介紹Java運(yùn)行時(shí)數(shù)據(jù)區(qū)的組成,Java內(nèi)存模型也是虛擬機(jī)里面的重點(diǎn),后面會(huì)多帶帶抽出一篇來進(jìn)行介紹。

1.運(yùn)行時(shí)數(shù)據(jù)區(qū)介紹

程序運(yùn)行所需的內(nèi)存空間,有些是不能在編譯期就能確定,得要在運(yùn)行期根據(jù)實(shí)際運(yùn)行狀況動(dòng)態(tài)地在系統(tǒng)中創(chuàng)建。Java虛擬機(jī)在執(zhí)行Java程序的過程中會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。這些區(qū)域都有各自的用途,以及創(chuàng)建和銷毀的時(shí)間,有的區(qū)域隨著虛擬機(jī)進(jìn)程的啟動(dòng)而存在,有些區(qū)域則依賴用戶線程的啟動(dòng)和結(jié)束而建立和銷毀。

如圖所示,堆和方法區(qū)是所有線程共享的公共區(qū)域,堆和方法區(qū)所占的內(nèi)存空間是由JVM負(fù)責(zé)管理的,在該區(qū)域內(nèi)的內(nèi)存分配是由HotSpot的內(nèi)存管理模塊維護(hù)的,而內(nèi)存的釋放工作則由垃圾收集器自動(dòng)完成。虛擬機(jī)棧、本地方法棧、程序計(jì)數(shù)器是線程的私有區(qū)域,每個(gè)線程都關(guān)聯(lián)著唯一的棧和程序計(jì)數(shù)器,并僅能使用屬于自己的那份棧空間和程序計(jì)算器來執(zhí)行程序。

2.堆(Heap)

對于大多數(shù)應(yīng)用來說,Java堆(Java Heap)是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊。堆是可供各個(gè)線程共享的運(yùn)行時(shí)內(nèi)存區(qū)域,在虛擬機(jī)啟動(dòng)的時(shí)候就被創(chuàng)建。此內(nèi)存區(qū)域的唯一目的就是存放對象實(shí)例,幾乎所有的對象實(shí)例都在這里分配內(nèi)存。這一點(diǎn)在Java虛擬機(jī)規(guī)范中的描述就是:所有的對象實(shí)例以及數(shù)組對象都要在堆上分配。但是隨著JIT編譯器的發(fā)展與逃逸分析技術(shù)逐漸成熟,棧上分配、標(biāo)量替換優(yōu)化技術(shù)將會(huì)導(dǎo)致一些微妙的變化發(fā)生,所有的對象都分配在堆上也漸漸變得不是那么“絕對”了。

Java堆的容量可以是固定的,也可以隨著程序執(zhí)行的需求動(dòng)態(tài)擴(kuò)展,并在不需要過多空間時(shí)自動(dòng)收縮。Java堆可以處于物理上不連續(xù)的內(nèi)存空間中,只要邏輯上是連續(xù)的即可。如果在堆中沒有內(nèi)存完成實(shí)例分配,并且堆也無法再擴(kuò)展時(shí),將會(huì)拋出OutOfMemoryError異常。

Java堆是垃圾收集器管理的主要區(qū)域,因此很多時(shí)候也被稱做“GC堆”(Garbage Collected Heap)。從內(nèi)存回收的角度來看,由于現(xiàn)在收集器基本都采用分代收集算法,Java虛擬機(jī)將堆劃分為新生代和老年代。其中,新生代又被分為Eden區(qū),以及兩個(gè)大小相同的Survivor區(qū)(From Survivor,To Survivor)。默認(rèn)情況下,Java虛擬機(jī)采取的是一種動(dòng)態(tài)分配的策略(JVM參數(shù)-XX:+UsePSAdaptiveSurvivorSizePolicy),根據(jù)生成對象的速率,以及Survivor區(qū)的使用情況,動(dòng)態(tài)調(diào)整Eden區(qū)和Survivor區(qū)的比例。也可以通過參數(shù)(SurvivorRatio)來調(diào)整這個(gè)比例,SurvivorRatio這個(gè)參數(shù)就是新生代中Eden區(qū)與Survivor區(qū)的容量比值,默認(rèn)是8,代表Eden:Survivor=8:1。

是否可能有兩個(gè)對象共用一段內(nèi)存的事故?

當(dāng)調(diào)用new指令時(shí),會(huì)在Eden區(qū)劃出一塊作為存儲(chǔ)對象的內(nèi)存。由于堆空間是線程共享的,因此直接在這里邊劃空間是需要進(jìn)行同步的。否則,將有可能出現(xiàn)兩個(gè)對象共用一段內(nèi)存的事故。解決方法就是,Java堆中可能劃出多個(gè)線程私有的分配緩沖區(qū)TLAB(Thread Local Allocation Buffer,對應(yīng)的虛擬機(jī)參數(shù)-XX:+UseTLAB,默認(rèn)開啟)。

具體來說,每個(gè)線程可以向Java虛擬機(jī)申請一段連續(xù)內(nèi)存,比如2048字節(jié),作為線程私有的TLAB。這個(gè)操作需要加鎖,線程需要維護(hù)兩個(gè)指針(實(shí)際上可能更多,但重要也就兩個(gè)),一個(gè)指向TLAB中空余內(nèi)存的起始位置,一個(gè)則指向TLAB末尾。接下來的new指令,便可以直接通過指針加法(bump the pointer),也有人叫做指針碰撞來實(shí)現(xiàn),即把指向空余內(nèi)存位置的指針加上所請求的字節(jié)數(shù)。如果加法后空余內(nèi)存指針的值仍小于或等于指向末尾的指針,則代表分配成功。否則,TLAB已經(jīng)沒有足夠的空間來滿足本次新建操作。這個(gè)時(shí)候,便需要當(dāng)前線程重新申請新的TLAB。

3.方法區(qū)(Method Area)

方法區(qū)與堆一樣是線程共享的,在虛擬機(jī)啟動(dòng)的時(shí)候創(chuàng)建,方法區(qū)可視為堆的一個(gè)邏輯部分,但是它卻有一個(gè)別名叫做Non-Heap(非堆),目的應(yīng)該是與Java堆區(qū)分開來。

方法區(qū)類似于傳統(tǒng)語言編譯后的代碼存儲(chǔ)區(qū)域,它存儲(chǔ)每個(gè)類的結(jié)構(gòu)信息,如:

常量池

方法數(shù)據(jù)

方法和構(gòu)造函數(shù)的字節(jié)碼

類、實(shí)例、接口初始化時(shí)用到的特殊方法

備注:《深入理解Java虛擬機(jī)》里將方法區(qū)歸納為用于存儲(chǔ)已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。

Java虛擬機(jī)規(guī)范對方法區(qū)的限制非常寬松,除了和Java堆一樣不需要連續(xù)的內(nèi)存和可以選擇固定大小或者可擴(kuò)展外,還可以選擇不實(shí)現(xiàn)垃圾收集。這區(qū)域的內(nèi)存回收目標(biāo)主要是針對常量池的回收和對類型的卸載。

4.程序計(jì)數(shù)器(Program Counter Register)

Java虛擬機(jī)可以支持多條線程同時(shí)執(zhí)行,每一條Java虛擬機(jī)線程都有自己的程序計(jì)數(shù)器。在任意時(shí)刻,一條Java虛擬機(jī)線程只會(huì)執(zhí)行一個(gè)方法的代碼,這個(gè)正在被線程執(zhí)行的方法稱為該線程的當(dāng)前方法(current methon)。如果這個(gè)方法不是native的,那程序計(jì)數(shù)器保存的就是Java虛擬機(jī)正在執(zhí)行的字節(jié)碼指令的地址。如果該方法是native方法,那程序計(jì)數(shù)器的值為空(undefined)。程序計(jì)數(shù)器的容量至少應(yīng)當(dāng)保存一個(gè)returnAddress類型的數(shù)據(jù)或者一個(gè)與平臺(tái)相關(guān)的本地指針的值。

程序計(jì)數(shù)器是一塊較小的內(nèi)存空間,它可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。此內(nèi)存區(qū)域是唯一一個(gè)在Java虛擬機(jī)規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域。

5.虛擬機(jī)棧(VM Stack)

每一條Java虛擬機(jī)線程都有自己私有的Java虛擬機(jī)棧,它的生命周期與線程相同。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個(gè)方法在執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀(stack frame)用于存儲(chǔ)局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息。每一個(gè)方法從調(diào)用直至執(zhí)行完成的過程,就對應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中入棧到出棧的過程。

Java虛擬機(jī)棧可能發(fā)生如下異常情況:

如果線程請求分配的棧容量超過Java虛擬機(jī)棧允許的最大容量,Java虛擬機(jī)將會(huì)拋出一個(gè)StackOverflowError異常。

如果Java虛擬機(jī)棧可以動(dòng)態(tài)擴(kuò)展,并且在嘗試擴(kuò)展的時(shí)候無法申請到足夠的內(nèi)存,或者在創(chuàng)建新的線程時(shí)沒有足夠的內(nèi)存區(qū)創(chuàng)建對應(yīng)的虛擬機(jī)棧,那Java虛擬機(jī)將會(huì)拋出一個(gè)OutOfMemoryError異常

6.本地方法棧(Native Method Stack)

本地方法棧與虛擬機(jī)棧所發(fā)揮的作用是非常相似的,它們之間的區(qū)別不過是虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則為虛擬機(jī)使用到的native方法服務(wù)。

Java虛擬機(jī)規(guī)范允許本地方法棧實(shí)現(xiàn)成固定大小或者根據(jù)計(jì)算來動(dòng)態(tài)擴(kuò)展和收縮。如果采用固定大小的本地方法棧,那么每一個(gè)線程的本地方法棧容量可以在創(chuàng)建棧的時(shí)候獨(dú)立選定。

與虛擬機(jī)棧一樣,本地方法棧區(qū)域也會(huì)拋出StackOverflowError和OutOfMemoryError異常。

7.擴(kuò)展知識(shí)點(diǎn) 7.1 棧上分配和逃逸分析

在棧中分配的基本思路是這樣的:分析局部變量的作用域僅限于方法內(nèi)部,則JVM直接在棧幀內(nèi)分配對象空間,避免在堆中分配。這個(gè)分析過程稱為逃逸分析(也有叫逸出分析),而棧幀內(nèi)分配對象的方式稱為棧上分配

這樣做的目的是減少新生代的收集次數(shù),間接提高JVM性能。虛擬機(jī)是允許堆逃逸分析開關(guān)進(jìn)行配置的,從Sun Java 6u23以后,HotSpot默認(rèn)開啟逃逸分析。

7.2 棧幀

棧幀是用于支持虛擬機(jī)進(jìn)行方法調(diào)用和方法執(zhí)行的數(shù)據(jù)結(jié)構(gòu),它是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)中的虛擬機(jī)棧的棧元素。棧幀存儲(chǔ)了方法的局部變量表、操作數(shù)棧、動(dòng)態(tài)連接和方法返回地址等信息每一個(gè)方法從調(diào)用開始至執(zhí)行完成的過程,都對應(yīng)著一個(gè)棧幀在虛擬機(jī)棧里面從入棧到出棧的過程。

在編譯程序代碼的時(shí)候,棧幀中需要多大的局部變量表,多深的操作數(shù)棧都已經(jīng)完全確定了,并且寫入到方法表的Code屬性之中。因此一個(gè)棧幀需要分配多少內(nèi)存,不會(huì)收到程序運(yùn)行期變量數(shù)據(jù)的影響,而僅僅取決于具體的虛擬機(jī)實(shí)現(xiàn)。

一個(gè)線程中的方法調(diào)用鏈可能會(huì)很長,很多方法都同時(shí)處于執(zhí)行狀態(tài)。對于執(zhí)行引擎來說,在活動(dòng)線程中,只有位于棧頂?shù)臈攀怯行У模Q為當(dāng)前棧幀(Current Stack Frame),與這個(gè)棧幀相關(guān)聯(lián)的方法稱為當(dāng)前方法(Current Method)。執(zhí)行引擎運(yùn)行的所有字節(jié)碼指令都只針對當(dāng)前棧幀進(jìn)行操作。棧幀的概念結(jié)構(gòu)如下:

8.運(yùn)行時(shí)數(shù)據(jù)區(qū)腦圖

高清、無碼、完整腦圖可以私信或留言告知哦!!!

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76256.html

相關(guān)文章

  • JVM小白學(xué)成大佬】1.開篇

    摘要:的重要性毋庸置疑,可以毫不夸張的說虛擬機(jī)是整個(gè)平臺(tái)的基石。方面的知識(shí),也一直是等大廠面試考核的重點(diǎn)。本專欄將分為如下幾個(gè)大模塊進(jìn)行分析開篇介紹運(yùn)行時(shí)數(shù)據(jù)區(qū)。最主要的是讓我知道能得到多少小伙伴的認(rèn)可,畢竟大家的認(rèn)可,就是不懈努力的動(dòng)力 JVM的重要性毋庸置疑,可以毫不夸張的說Java虛擬機(jī)是整個(gè)Java平臺(tái)的基石。 JVM方面的知識(shí),也一直是BAT等大廠面試考核的重點(diǎn)。特別是JVM調(diào)優(yōu),...

    姘存按 評論0 收藏0
  • 《深入理解Java虛擬機(jī)》(二)Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)

    摘要:虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)分為以下幾個(gè)部分。程序計(jì)數(shù)器也是在虛擬機(jī)規(guī)范中唯一沒有規(guī)定任何異常情況的區(qū)域。在方法運(yùn)行期間不會(huì)改變局部變量表的大小。長度在位和位的虛擬機(jī)中,分別為官方稱它為。 Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū) 詳解 2.1 概述 本文參考的是周志明的 《深入理解Java虛擬機(jī)》第二章 ,為了整理思路,簡單記錄一下,方便后期查閱。 2.2 運(yùn)行時(shí)數(shù)據(jù)區(qū)域 Java虛擬機(jī)在Java程序運(yùn)行時(shí)...

    draveness 評論0 收藏0
  • java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)

    摘要:虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)虛擬機(jī)在執(zhí)行程序的過程中會(huì)把它管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。此內(nèi)存區(qū)域是唯一一個(gè)在虛擬機(jī)規(guī)范中沒有規(guī)定任何情況的區(qū)域。 showImg(https://segmentfault.com/img/bVbvueY?w=1600&h=800); java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū) java虛擬機(jī)在執(zhí)行java程序的過程中會(huì)把它管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。根據(jù)《Ja...

    sunnyxd 評論0 收藏0
  • 13張圖解就能讓女朋友徹底了解Java中的內(nèi)存模型,快上車!

    摘要:前言了解中的對象變量等存放的內(nèi)存區(qū)域十分重要本文將全面講解虛擬機(jī)中的內(nèi)存模型分區(qū),希望你們會(huì)喜歡目錄張圖解就能讓女朋友徹底了解中的內(nèi)存模型,快上車虛擬機(jī) 前言了解Java中的對象、變量等存放的內(nèi)存區(qū)域十分重要本文將全面講解Java虛擬機(jī)中的內(nèi)存模型 & 分區(qū),希望你們會(huì)喜歡目錄1、內(nèi)存模型 & 分區(qū)Java虛擬機(jī)在運(yùn)行Ja...

    番茄西紅柿 評論0 收藏2637
  • 《深入理解JVM》讀書筆記

    摘要:抽時(shí)間重新讀了一遍深入理解一書。驗(yàn)證確保文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會(huì)危害虛擬機(jī)自身的安全。可見性可見性是指當(dāng)一個(gè)線程修改了共享變量的值,其他線程能夠立即得知這個(gè)修改。 抽時(shí)間重新讀了一遍《深入理解JVM》一書。以下為摘錄內(nèi)容。 1 java內(nèi)存區(qū)域 showImg(https://segmentfault.com/img/bVboDgk?w=617&h=365...

    idealcn 評論0 收藏0

發(fā)表評論

0條評論

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