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

資訊專欄INFORMATION COLUMN

【JVM從小白學成大佬】2.Java虛擬機運行時數據區

shuibo / 3633人閱讀

摘要:虛擬機在執行程序的過程中會把它所管理的內存劃分為若干個不同的數據區域。棧幀棧幀是用于支持虛擬機進行方法調用和方法執行的數據結構,它是虛擬機運行時數據區中的虛擬機棧的棧元素。棧幀的概念結構如下運行時數據區腦圖高

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

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

本篇將給各位小伙伴先詳細介紹Java運行時數據區的組成,Java內存模型也是虛擬機里面的重點,后面會多帶帶抽出一篇來進行介紹。

1.運行時數據區介紹

程序運行所需的內存空間,有些是不能在編譯期就能確定,得要在運行期根據實際運行狀況動態地在系統中創建。Java虛擬機在執行Java程序的過程中會把它所管理的內存劃分為若干個不同的數據區域。這些區域都有各自的用途,以及創建和銷毀的時間,有的區域隨著虛擬機進程的啟動而存在,有些區域則依賴用戶線程的啟動和結束而建立和銷毀。

如圖所示,堆和方法區是所有線程共享的公共區域,堆和方法區所占的內存空間是由JVM負責管理的,在該區域內的內存分配是由HotSpot的內存管理模塊維護的,而內存的釋放工作則由垃圾收集器自動完成。虛擬機棧、本地方法棧、程序計數器是線程的私有區域,每個線程都關聯著唯一的棧和程序計數器,并僅能使用屬于自己的那份??臻g和程序計算器來執行程序。

2.堆(Heap)

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

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

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

是否可能有兩個對象共用一段內存的事故?

當調用new指令時,會在Eden區劃出一塊作為存儲對象的內存。由于堆空間是線程共享的,因此直接在這里邊劃空間是需要進行同步的。否則,將有可能出現兩個對象共用一段內存的事故。解決方法就是,Java堆中可能劃出多個線程私有的分配緩沖區TLAB(Thread Local Allocation Buffer,對應的虛擬機參數-XX:+UseTLAB,默認開啟)。

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

3.方法區(Method Area)

方法區與堆一樣是線程共享的,在虛擬機啟動的時候創建,方法區可視為堆的一個邏輯部分,但是它卻有一個別名叫做Non-Heap(非堆),目的應該是與Java堆區分開來。

方法區類似于傳統語言編譯后的代碼存儲區域,它存儲每個類的結構信息,如:

常量池

方法數據

方法和構造函數的字節碼

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

備注:《深入理解Java虛擬機》里將方法區歸納為用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。

Java虛擬機規范對方法區的限制非常寬松,除了和Java堆一樣不需要連續的內存和可以選擇固定大小或者可擴展外,還可以選擇不實現垃圾收集。這區域的內存回收目標主要是針對常量池的回收和對類型的卸載。

4.程序計數器(Program Counter Register)

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

程序計數器是一塊較小的內存空間,它可以看作是當前線程所執行的字節碼的行號指示器。此內存區域是唯一一個在Java虛擬機規范中沒有規定任何OutOfMemoryError情況的區域。

5.虛擬機棧(VM Stack)

每一條Java虛擬機線程都有自己私有的Java虛擬機棧,它的生命周期與線程相同。虛擬機棧描述的是Java方法執行的內存模型:每個方法在執行的同時都會創建一個棧幀(stack frame)用于存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。每一個方法從調用直至執行完成的過程,就對應著一個棧幀在虛擬機棧中入棧到出棧的過程。

Java虛擬機??赡馨l生如下異常情況:

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

如果Java虛擬機棧可以動態擴展,并且在嘗試擴展的時候無法申請到足夠的內存,或者在創建新的線程時沒有足夠的內存區創建對應的虛擬機棧,那Java虛擬機將會拋出一個OutOfMemoryError異常

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

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

Java虛擬機規范允許本地方法棧實現成固定大小或者根據計算來動態擴展和收縮。如果采用固定大小的本地方法棧,那么每一個線程的本地方法棧容量可以在創建棧的時候獨立選定。

與虛擬機棧一樣,本地方法棧區域也會拋出StackOverflowError和OutOfMemoryError異常。

7.擴展知識點 7.1 棧上分配和逃逸分析

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

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

7.2 棧幀

棧幀是用于支持虛擬機進行方法調用和方法執行的數據結構,它是虛擬機運行時數據區中的虛擬機棧的棧元素。棧幀存儲了方法的局部變量表、操作數棧、動態連接和方法返回地址等信息。每一個方法從調用開始至執行完成的過程,都對應著一個棧幀在虛擬機棧里面從入棧到出棧的過程。

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

一個線程中的方法調用鏈可能會很長,很多方法都同時處于執行狀態。對于執行引擎來說,在活動線程中,只有位于棧頂的棧幀才是有效的,稱為當前棧幀(Current Stack Frame),與這個棧幀相關聯的方法稱為當前方法(Current Method)。執行引擎運行的所有字節碼指令都只針對當前棧幀進行操作。棧幀的概念結構如下:

8.運行時數據區腦圖

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/76256.html

相關文章

  • JVM小白學成大佬】1.開篇

    摘要:的重要性毋庸置疑,可以毫不夸張的說虛擬機是整個平臺的基石。方面的知識,也一直是等大廠面試考核的重點。本專欄將分為如下幾個大模塊進行分析開篇介紹運行時數據區。最主要的是讓我知道能得到多少小伙伴的認可,畢竟大家的認可,就是不懈努力的動力 JVM的重要性毋庸置疑,可以毫不夸張的說Java虛擬機是整個Java平臺的基石。 JVM方面的知識,也一直是BAT等大廠面試考核的重點。特別是JVM調優,...

    姘存按 評論0 收藏0
  • 《深入理解Java虛擬機》(二)Java虛擬機運行時數據

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

    draveness 評論0 收藏0
  • java虛擬機運行時數據

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

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

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

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

    摘要:抽時間重新讀了一遍深入理解一書。驗證確保文件的字節流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全??梢娦钥梢娦允侵府斠粋€線程修改了共享變量的值,其他線程能夠立即得知這個修改。 抽時間重新讀了一遍《深入理解JVM》一書。以下為摘錄內容。 1 java內存區域 showImg(https://segmentfault.com/img/bVboDgk?w=617&h=365...

    idealcn 評論0 收藏0

發表評論

0條評論

shuibo

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<