JVM堆空間用途分析與劃分依據

在上一次【http://www.javashuo.com/article/p-swojvntv-dg.html】已經對JVM的內存空間的劃分進行了理論化的學習,此次仍是對上一次提到的理論進行進一步的補充,純知識鞏固,先來回顧一下上節JVM整個內存都由哪些構成:html

下面則按照上述提到的順序過一下:web

虛擬機棧:算法

回顧一下上節作的筆記:數據結構

知識補充:多線程

一個虛擬機棧它自己是歸屬於一上特定的線程的,換言之它是屬於線程私有的內存空間。當線程開始運行的時候,與之相關的虛擬機棧就誕生了,而當線程消亡了,與之對應的虛擬機棧也就消失不見了。虛擬機棧裏面的數據則爲棧幀(Stack Frame),它主要是用來存儲與線程操做相關的一些具體數據或者是數據結構,如以前學習的操做數棧、局部變量表,方法的出入口等,裏面能夠存放基本數據類型,也能夠存放其引用類型(注意:引用類型不是對象!),引用類型是存儲在局部變量表中,也就是放在棧幀裏面的,也就是屬於虛擬機棧。而對於虛擬機棧會存在StackOverFlow異常【以後會用代碼來瞅一下】,也有可能出現OutOfMemory異常【但極少會出現】。oracle

程序計數器:學習

回顧一下上節作的筆記:spa

知識補充:線程

它跟虛擬機棧也相似,也是屬於線程私有的數據結構。在多線程的環境下,可是在同一時刻確定只會有一個線程在執行,只是按照時間片的方式來切換線程就感受是多個線程同時在執行同樣,這裏有這麼一個問題:當一個線程執行到一半的時候核心切到了第二個線程了,勢必要記錄當前線程要掛起到什麼位置上,此信息就是記錄在程序計數器上的,而每個程序計數器裏面的線程執行的信息實際上是線程私有的,也就是說A線程是不能獲得B線程的程序計數器的。若是一個程序正在執行某一個Java方法,程序計數器記錄的就是正在執行字節碼對應的地址而已。3d

因此要記住:虛擬機棧和程序計數器是線程不共享的!

本地方法棧:

回顧一下上節作的筆記:

知識補充:

本地方法棧的主要結構其實跟虛擬機棧的結構相似,它們本質上沒有特別大的區別,有些虛擬機會將本地方法棧和虛擬機棧合二爲一,最典型的就是oracle的haspot虛擬機。一樣它也有可能會出現StackOverFlow棧異常。

堆(Heap):

回顧一下上節作的筆記:

知識補充:

這塊也是將來要花重點來透徹理解和研究的,堆內存上的對象是被全部線程所共享的,與堆相關的一個重要概念就是垃圾收集器【將來會詳細來學習的】,如今幾乎全部的垃圾收集器都是採用的分代收集算法,因此,堆空間也基於這一點進行了相應的劃分:新生代和老年代【基本上都據說它,但也僅僅據說過】,而與之相關的還有這三個概念:Eden空間、From Survivor空間和To Survivor空間。關於新生代和老年代這裏稍加解釋一下,在將來會詳細學習的,「通常」狀況下建立了一個對象,該對象就會進入到了新生代了,新生代也是內存的一個區域,過了一段時間以後GC會對堆上的內存進行回收,因爲該對像還能被GC ROOT所引用因此這一次的GC就沒有被回收,接着又過一段時間GC執行該對象仍是能被GC ROOT所引用因此仍是木有被回收,第三次當GC又嘗試進行回收該對象仍是沒能被回收,有可能出現了五次以後,此對象就會晉升到老年代,所謂老年代就是指裏面的對象存活的比較久,而老年代垃圾回收的頻率確定是要比新生代要低不少的。

另外JVM對於Java的堆空間而言,這個空間在物理內存既能夠是連續存放的,也能夠是不連續的,

方法區(Method Area):

回顧一下上節作的筆記:

知識補充:

如上面描述它是用來存儲元信息的,而元信息能夠指類對象的基本信息、常量的一些信息等。其中說到永久代是不多會被回收的,可是不是說在方法區中的內存是不會被回收的,好比當類被卸載了相應的方法區的內存也就被回收的,只是這種狀況出現得較少而已。

運行時常量池:

回顧一下上節作的筆記:

這個比較熟悉了,沒啥可補充的了。

直接內存(Direct Memory):

回顧一下上節作的筆記:

知識補充:

其實這部分是跟Java NIO【關於這塊還不太熟悉,待將來學習時再來體會】密切相關的,JVM經過堆上的DirectByteBuffer來操做直接內存,因此效率是比較高的。

 

以上至關因而對上一次知識的複習鞏固,雖然說枯燥可是很重要!!

相關文章
相關標籤/搜索