java虛擬機器:JVM記憶體模型

來源:互聯網
上載者:User

標籤:執行個體   線程   方便   back   載入   output   代碼   overflow   獨立   

一、JVM記憶體模型圖解

JVM 運行時資料區 (JVM Runtime Area) 其實就是指 JVM 在運行期間,其對JVM記憶體空間的劃分和分配。網上找到兩幅圖如下所示(個人認為第二個圖Native Method Stack應該畫在Java Thead模組中):

    

二、各資料區域介紹 1、

棧分為java虛擬機器棧和本地方法棧

  • 重點是Java虛擬機器棧,它是線程私人的,生命週期與線程相同。
  • 每個方法執行都會建立一個棧幀,用於存放局部變數表,操作棧,動態連結,方法出口等。每個方法從被調用,直到被執行完。對應著一個棧幀在虛擬機器中從入棧到出棧的過程。
  • 通常說的棧就是指局部變數表部分,存放編譯期間可知的8種基礎資料型別 (Elementary Data Type),及對象引用和指令地址。局部變數表是在編譯期間完成分配,當進入一個方法時,這個棧中的局部變數分配記憶體大小是確定的。
  • 會有兩種異常StackOverFlowError和 OutOfMemoneyError。當線程請求棧深度大於虛擬機器所允許的深度就會拋出StackOverFlowError錯誤;虛擬機器棧動態擴充,當擴充無法申請到足夠的記憶體空間時候,拋出OutOfMemoneyError。
  • 本地方法棧為虛擬機器使用到的本地方法服務(native),也是線程私人的。
2、堆區
  • 堆被所有線程共用地區,在虛擬機器啟動時建立,唯一目的存放對象執行個體。
  • 堆區是gc的主要區域,通常情況下分為兩個區塊年輕代和年老代。更細一點年輕代又分為Eden區最要放新建立對象,From survivor 和 To survivor 儲存gc後倖存下的對象,預設情況下各自佔比 8:1:1。 
    不過很多文章介紹分為3個區塊,把方法區算著為永久代。這大概是基於Hotspot虛擬機器劃分, 然後比如IBM j9就不存在永久代概論。不管怎麼分區,都是存放對象執行個體。
  • 會有異常OutOfMemoneyError
3、方法區
  • 被所有線程共用地區,用於存放已被虛擬機器載入的類資訊,常量,靜態變數等資料。被Java虛擬機器描述為堆的一個邏輯部分。習慣是也叫它永久代(permanment generation)
  • 記憶體回收很少光顧這個地區,不過也是需要回收的,主要針對常量池回收,類型卸載。
  • 常量池用於存放編譯期產生的各種位元組碼和符號引用,常量池具有一定的動態性,裡面可以存放編譯期產生的常量;運行期間的常量也可以添加進入常量池中,比如string的intern()方法。
4、程式計數器
  • 當前線程所執行的行號指標。通過改變計數器的值來確定下一條指令,比如迴圈,分支,跳轉,異常處理,線程恢複等都是依賴計數器來完成。
  • Java虛擬機器多線程是通過線程輪流切換並分配處理器執行時間的方式實現的。為了線程切換能恢複到正確的位置,每條線程都需要一個獨立的程式計數器,所以它是線程私人的。
  • 唯一一塊Java虛擬機器沒有規定任何OutofMemoryError的區塊
三、資料區域匯總

名稱

特徵

作用

配置參數

異常

程式計數器

佔用記憶體小,線程私人,生命週期與線程相同

大致為位元組碼行號指標

虛擬機器棧

線程私人,生命週期與線程相同,使用連續的記憶體空間

Java 方法執行的記憶體模型,儲存局部變數表、操作棧、動態連結、方法出口等資訊

-Xss

StackOverflowError

OutOfMemoryError

java堆

線程共用,生命週期與虛擬機器相同,可以不使用連續的記憶體位址

儲存對象執行個體,所有對象執行個體(包括數組)都要在堆上分配

-Xms

-Xsx

-Xmn

OutOfMemoryError

方法區

線程共用,生命週期與虛擬機器相同,可以不使用連續的記憶體位址

儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的代碼等資料

-XX:PermSize:16M

-XX:MaxPermSize:64M

OutOfMemoryError

運行時常量池

方法區的一部分,具有動態性

存放字面量及符號引用

 

 

四、延伸:直接記憶體

直接記憶體(Direct Memory)並不是虛擬機器運行時資料區的一部分,也不是Java虛擬機器規範中定義的記憶體地區,但是這部分記憶體也被頻繁地使用,而且也可能導致OutOfMemoryError 異常出現,所以我們放到這裡一起講解。

在JDK 1.4 中新加入了NIO(NewInput/Output)類,引入了一種基於通道(Channel)與緩衝區(Buffer)的I/O 方式,它可以使用Native 函數庫直接分配堆外記憶體,然後通過一個儲存在Java 堆裡面的DirectByteBuffer 對象作為這塊記憶體的引用進行操作。這樣能在一些情境中顯著提高效能,因為避免了在Java 堆和Native 堆中來回複製資料。

五、延伸:堆與棧的對比

經常有人把Java 記憶體區分為堆記憶體(Heap)和棧記憶體(Stack),這種分法比較粗糙,Java記憶體地區的劃分實際上遠比這複雜。這種劃分方式的流行只能說明大多數程式員最關注的、與對象記憶體配置關係最密切的記憶體地區是這兩塊。

堆很靈活,但是不安全。對於對象,我們要動態地建立、銷毀,不能說後建立的對象沒有銷毀,先前建立的對象就不能銷毀,那樣的話我們的程式就寸步難行,所以Java中用堆來儲存物件。而一旦堆中的對象被銷毀,我們繼續引用這個對象的話,就會出現著名的 NullPointerException,這就是堆的缺點——錯誤的引用邏輯只有在運行時才會被發現。

棧不靈活,但是很嚴格,是安全的,易於管理。因為只要上面的引用沒有銷毀,下面引用就一定還在,在大部分程式中,都是先定義的變數、引用先進棧,後定義的後進棧,同時,區塊內部的變數、引用在進入區塊時壓棧,區塊結束時出棧,理解了這種機制,我們就可以很方便地理解各種程式設計語言的範圍的概念了,同時這也是棧的優點——錯誤的引用邏輯在編譯時間就可以被發現。

棧--主要存放引用和基礎資料型別 (Elementary Data Type)。

堆--用來存放 new 出來的對象執行個體。

 

參考:http://blog.csdn.net/u012152619/article/details/46968883

 

java虛擬機器:JVM記憶體模型

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.