JVM-內存結構概述

一、 java虛擬機原理

所謂虛擬機,就是一臺虛擬的機器。他是一款軟件,用來執行一系列虛擬計算指令,大體上虛擬機可以分爲
系統虛擬機和程序虛擬機, 大名鼎鼎的Visual Box、Vmare就屬於系統虛擬機,他們完全是對物理計算的仿真,提供了一個可以運行完整操作系統的軟件平臺。
程序虛擬機典型代碼就是Java虛擬機,它專門爲執行單個計算程序而計算,在Java虛擬機中執行的指令我們成爲Java自己碼指令。無論是系統虛擬機還是程序虛擬機,在上面運行的軟件都被限制於虛擬機提供的資源中。
Java發展至今,出現過很多虛擬機,做初Sun使用的一款叫ClassIc的Java虛擬機,到現在引用最廣泛的是HotSpot虛擬機,除了Sum以外,還有BEA的Jrockit,目前Jrockit和HostSopt都被oralce收入旗下,大有整合的趨勢。

1.1Java內存模型和java內存結構的混淆:

java內存模型和java內存結構不相同,雖然只差兩個字,卻沒什麼關係。
java內存模型是和多線程JMM相關的知識點,二java內存結構是指JVM虛擬機存儲空間,所以兩者關係不大。

二 、java內存結構

java虛擬機在執行java程序的過程中會把他所管理的內存劃分爲若干個數據區域。各區域都有各自的用途,和創建和銷燬的時間,有些隨着程序的啓動而存在,有些則依賴用戶線程的啓動和結束而建立和銷燬。所以JVM所管理的內存會包括一下幾個運行時數據區域:

方便理解的一張結構圖:

java內存結構圖

2.1 方法區

方法區,存放的是被static關鍵字修飾的,常量信息。也可以理解爲全局的變量都會放到方法區內,方法區會在被class文件被加載時就會被初始化,放入方法區,而且被線程共享,所以會有線程安全問題。
如果系統定義了太多的類,會導致方法區溢出。虛擬機會拋出內存溢出的錯誤。
當方法區無法滿足內存分配需求時,將拋出OutOfMemoryError異常。

2.2 java堆

堆內存存放的是:創建出的對象;new創建;數組。堆會被線程共享
java堆是GC的主要區域。由於GC基本都是採用分代收集算法,所以在堆中還可以細分爲:新生代、老年代;

  1. 新生代:剛創建的對象,先放到新生代,GC會經常光顧新生代中的對象
  2. 老年代:如果對象頻繁的使用,對象放入到老年代中,GC很少會光顧老年代中的對象

再細緻一點可以分爲:Eden空間、From Survivor空間、To Survivor空間等。無論哪個空間存放的都是對象實例,進一步劃分只是方便更好的回收內存,或更快的分配內存。

新生代有三個區域:Eden區、s0區、s1區。

  • 剛創建的對象會放到新生代中的Eden區。
  • s0區域s1區大小相當,目的是垃圾回收機制的複製算法

java堆可以處於物理上不連續的空間中,只要邏輯上是連續的即可,就想磁盤空間一樣,在實現時可以固定空間大小,也可以是可擴展的。不過當前主流虛擬機都是按照可擴展實現的(通過-Xmx和-Xms控制)。
如果堆中沒有內存完成實例分配,並且堆也無法擴展時,將會拋出OutOfMemorError異常。

2.3 棧

棧內存存放的是:定義的基本局變量,棧內代碼運行完畢,便會自動釋放內存。棧內存每個線程私有,互不共享,棧內存不會產生線程安全問題。

棧的生命週期與線程相同,每個方法在執行的同時都會創建一個棧幀,用於存儲局部變量、操作數幀、動態鏈接、方法出口等信息。每個方法調用直至執行完畢的過程, 就對應着一個棧幀在虛擬機棧中入棧到出棧的過程。

在棧的區域有兩種異常狀況:
如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常;
如果虛擬機棧可以動態擴展,如果擴展時無法申請到足夠的內存時,就會拋出OutOfMemoryError異常。(當前大部分java虛擬機都可動態擴展,只不過java虛擬機規範中也允許固定長度的虛擬機棧)

2.4 本地方法棧

本地方法棧和虛擬機棧所發揮的作用非常相似,它們的區別是:
虛擬機棧執行java方法(字節碼)服務,而本地方法棧則爲虛擬機使用到的Native方法服務。
本地方法棧也會拋出StackOverflowError異常和OutOfMemoryError異常。

2.4 程序計數器

這是一塊較小的內存空間,它可以看做當前線程所執行的字節碼的行號指示器。字節碼解釋器工作室就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個技術器來完成。爲了線程切換後能恢復到正確的執行位置,每條線程都需要有一個獨立的程序計數器,各線程之間計數器互不影響,獨立存儲,所以此區域是線程私有的,也就是線程安全的。

2.5 運行時常量池

運行時常量池是方法區的一部分。存儲的是編譯期生成的各種字面量和符號引用,這部分將在類加載後進入方法區的運行時常量池中存放。

2.6 直接內存

在深入理解Java虛擬機_JVM高級特性與最佳實踐 第2版中看到
直接內存描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章