虛擬機中的內存結構根據虛擬機規範劃分出了五個經常使用區域,這些區域各自有各自的用途,有些隨用戶線程而存在,有些則隨虛擬機進程而存在。
五個區域分別爲,虛擬機棧,本地方法棧,程序計數器,堆,方法區java
程序計數器是隨線程而生的,它是線程獨立的,用來記錄當前線程的字節碼與指令,保證下一次線程喚醒以後,能回到正確的執行位置,說白了就是線程喚醒能繼續執行。
程序計數器是一塊很是小的內存區域,也是惟一一個沒有規定任何OutOfMemoryError的區域算法
虛擬機棧也是線程私有的,它描述了Java方法執行的內存模型:每一個方法被執行是都會建立一個幀棧(Stack Frame) 用於存儲 局部變量表 操做數棧 動態連接 方法出口。每個方法被調用直至執行完成的過程,就是對應着一個幀棧在虛擬機棧中從入棧到出棧的過程。
局部變量表存放了編譯期可知的基本類型和引用類型。
在這個區域中,虛擬機規範規定了兩種異常狀況,StackOverflowError:當線程請求棧的深度大於虛擬機容許的深度,將會拋出此異常。 OutOfMemoryErro:當虛擬機棧在動態擴展長度時,沒法申請到足夠內存時將會拋出此異常數組
本地方法棧與虛擬機棧發揮的做用很是相似,主要是爲本地方法服務,虛擬機棧是爲Java 方法服務的。 有些虛擬機實現 如 HotSpot 已經將NM Stack 和VM Stack 合二爲一了函數
heap 是java 虛擬機管理的內存中最大的一塊,也是線程共享的。在虛擬機啓動時 自動建立。
除了JIT編譯和逃逸分析技術下的對象,絕大多數的對象實例和數組都在堆上分配。
同時 堆也是 垃圾收集器(Garbage Collection)主要工做的區域。
若是堆中沒有可分配的內存空間會拋出OutOfMemoryError性能
方法區與堆同樣 是線程共享的,用於存儲常量,靜態變量,加載的類信息,即時編譯的代碼數據塊。雖然說 虛擬機規範把方法區化爲堆的一部分,它卻又一個別名non-heap,有意把它和堆區分開了,有些地方也把這地方稱爲,永久代,主要是由於把GC收集擴展至這個區域了或者說用永久代來實現方法區的功能。
當方法去沒法知足內存分配需求時,將會拋出OutOfMemoryError
方法去主要存有:
*類信息
*類變量
*類型常量池
*方法信息
String常量池即是其中之一。ui
直接內存(Direct Memory)並非虛擬機運行時數據區的一部分,也不是Java
虛擬機規範中定義的內存區域,可是這部份內存也被頻繁地使用,並且也可能致使
OutOfMemoryError 異常出現,因此咱們放到這裏一塊兒講解。
在JDK 1.4 中新加入了NIO(New Input/Output)類,引入了一種基於通道(Channel)
與緩衝區(Buffer)的I/O 方式,它可使用Native 函數庫直接分配堆外內存,然
後經過一個存儲在Java 堆裏面的DirectByteBuffer 對象做爲這塊內存的引用進行
操做。這樣能在一些場景中顯著提升性能,由於避免了在Java 堆和Native 堆中來
回覆制數據。spa
heap 中內存劃分基於分代思想 主要分爲 新生代,老年代和存活區。 線程
大多數狀況下,對象在新生代中分配。當Eden區沒有足夠的空間的時候會發起一次MinorGC指針
大對象直接進入老年代,所謂大對象就是指須要大量連續內存空間的Java 對象,如數組,字符串等。
同時基於分代思想,虛擬機給每一個對象定義了一個對象年齡。當對象在Eden區通過MinorGC後還生存下來後,會被移動到Suivior Space中並記爲年齡爲1,而且在Suivior Space 每通過一次GC後 對其中存活的對象年齡加1,當對象年齡超過必定的閾值(默認爲15)時,將會被移動到老年代。對象
存活區有點像青年代,用於那些新生代存活下來而未到達老年代的對象。
同時 存活區分爲From,to 兩塊空間相同的區域,做爲複製回收算法的區域若是隻是按照對象年齡閥值來判斷是否須要移動到老年代,難以應付多變的內存狀況,加入在存活區有着很是大量的年輕對象(2,3,4,5,6,7歲等)以致於 存活區內存不太夠用的狀況。對於這種狀況,survivor有一個動態年齡斷定。在存活區中的相同年齡的全部對象大小的總和大於Survivor空間的一半,年齡大於或等於該年齡的對象就直接進入老年代。
Object obj = new Object()
Object obj 聲明瞭一個引用對象
new Object() 在堆中開闢了空間並生成對象
所謂對象的訪問方式是指,引用類型obj如何定位到堆中的具體對象Object()的。虛擬機中主流的方式有兩種直接指針和句柄池
若是使用句柄訪問方式,堆中會劃分出一小塊內存做爲句柄池,reference存儲的是對象的句柄地址,而句柄中包含了對象實例數據和各自數據的具體地址信息。優勢在於,reference存儲的是穩定的句柄地址,在對象被移動時,只會改變句柄中的實例數據指針,reference自己不須要改變。
若是使用餓了直接指針訪問,reference中直接存儲了對象的地址。次方式的優勢在於節約對象訪問方式,對於頻繁的訪問對象,直接指針節約了一個層級的訪問時間。