<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一文看懂 JVM 內(nèi)存區(qū)域分布與作用

          共 1850字,需瀏覽 4分鐘

           ·

          2021-06-09 10:46

          作者:bingfeng

          來源:SegmentFault 思否社區(qū)


          那么我們在開始介紹Java內(nèi)存區(qū)域之前,我們先放一張內(nèi)存區(qū)域的圖,方便我們后面介紹的時候可以對照著看。


          須知,本文是根據(jù)JDK8來介紹的。



          程序計數(shù)器



          首先它是線程私有的,它也稱為代碼的行號指示器,字節(jié)碼解釋器就是通過改變程序計數(shù)器的位置來確定下一行要執(zhí)行的代碼,它不存在OOM。


          如果線程正在執(zhí)行一個Java方法,那么它記錄的是正在執(zhí)行虛擬機字節(jié)碼指令的地址,如果是一個本地方法那么它的值為空。


          Java 虛擬機棧



          它也是線程私有的,它的聲明周期和線程一致。每個線程創(chuàng)建時都會創(chuàng)建一個虛擬機棧,內(nèi)部保存了一個個的棧幀,每個棧幀就對應著一次方法的調(diào)用。既然知道了虛擬機棧里面存放的是一個個的棧幀,那么也不難猜出虛擬機棧里面都存儲了什么東西。


          Java虛擬機棧是存在OOM的,當線程所請求的棧的深度大于虛擬機棧的深度或者虛擬機??梢詣討B(tài)擴容,當棧擴展時無法申請到足夠的內(nèi)存時,就會拋出OOM。


          • 虛擬機棧內(nèi)部結構


          • 局部變量表

            主要存儲方法的參數(shù),所有的基本類型數(shù)據(jù)和對象地址,以及返回地址類型(return address)。它以變量槽為最小的存儲單位,Java虛擬機并沒有規(guī)定一個變量槽占用多少內(nèi)存空間,但是規(guī)定了一個變量槽可以存放一個32位以內(nèi)的數(shù)據(jù)類型。如果存儲的數(shù)據(jù)類型超過32位,比如long、double,那么就使用兩個變量槽進行存儲。


          • 操作數(shù)棧

            操作數(shù)棧是一個先進后出的操作數(shù)棧,當一個方法剛開始執(zhí)行的時候,一個新的棧幀也會隨之被創(chuàng)建出來,這個方法的操作數(shù)棧是空的,它主要用于保存計算過程的中間結果,同時作為計算過程中變量臨時的存儲空間。如果被調(diào)用的方法有返回值,那么返回值將會被壓入當前棧幀的操作數(shù)棧中。操作數(shù)棧并非采用索引的方式進行數(shù)據(jù)訪問,而是通過入棧(push)和出棧(pop)操作來完成數(shù)據(jù)的訪問。


          • 動態(tài)鏈接

            大白話就是,棧幀中保存了一個方法的引用,當執(zhí)行方法的時候,可以拿著這個引用到運行時常量池中找到這個方法。

            動態(tài)鏈接的作用就是將這些方法的符號引用轉換為調(diào)用方法的直接引用。



          • 方法返回地

            就是在方法執(zhí)行結束之后,要返回下一條要執(zhí)行代碼位置的值,也就是程序計數(shù)器的值。

            那么除了方法正常執(zhí)行結束退出外,還有另外一種情況就是異常導致的方法退出,那么這種情況下是不會返回任何值的。對于拋出的異常,棧幀中不會做任何記錄,但是會記錄在一個異常表中。












          本地方法棧



          Java虛擬機棧為虛擬機執(zhí)行Java方法服務,本地方法棧則為虛擬機使用到的本地方法服務。像JVM就有好多C語言寫的方法,這個就需要本地方法棧來執(zhí)行。

          Java堆



          Java堆是虛擬機中最大的一塊內(nèi)存空間,它被所有的線程共享,在虛擬機啟動時創(chuàng)建。它唯一的目的就是存放對象實例。

          如果面試被問到,所有的對象實例都是在堆中分配內(nèi)存嗎?這個時候你一定要回答,不是。

          隨著即時編譯技術的發(fā)展進步,尤其是逃逸分析技術的日漸強大,棧上分配、變量替換等優(yōu)化手段,讓實例在”只在堆“中分配不再成為絕對。

          Java堆是垃圾收集的主要區(qū)域,Java堆中也經(jīng)常出現(xiàn)新生代、老年代、永久代等等,這里需要注意,這些并不是Java堆物理上的內(nèi)存布局,它是作為垃圾收集器而劃分一種內(nèi)存布局。

          方法區(qū)



          方法區(qū)也是線程共享的區(qū)域,它主要用于存儲被虛擬機加載的類型信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼緩存等數(shù)據(jù)。
          方法區(qū)它是可以被垃圾收集器進行回收的,主要針對類型的卸載和常量池的回收。

          方法區(qū)也可以產(chǎn)生OOM,當方法區(qū)無法滿足新的內(nèi)存分配需求時,將拋出OutOfMemoryError異常。

          運行時常量池



          運行時常量池是方法區(qū)的一部分。Class文件中除了有類的版本、字段、方法、接口等信息外,還有一項信息是常量池表,它用來存儲編譯期生成的各種字面量和符號引用。

          如果動態(tài)鏈接那塊沒看懂,那么看了運行常量池再翻回去看看是不是好理解了。



          點擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動和交流,掃描下方”二維碼“或在“公眾號后臺回復“ 入群 ”即可加入我們的技術交流群,收獲更多的技術文章~

          - END -


          瀏覽 90
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲欧美内射 | 欧美大屌在线观看视频 | 一区高清无码 | 亚洲午夜视频 | 黄片小视频在线观看 |