Java虛擬機的內存管理主要分兩點:內存分配以及內存回收。·java
1、內存分配圖:數組
注: 所佔區域的大小與實際的內存大小比例並沒有直接關係。多線程
解讀:.net
一、如圖,分紅兩種顏色的內存區域,其中藍色的是線程隔離的數據區,也就是說每個線程都有本身的這麼一個區域存放本身的數據,而青色區域則是線程共享的,裏面的數據爲全部線程共有,原則上都有權限訪問。線程
二、程序計數器:翻譯
用途:用來給程序導航指路的。這個是一塊較小的內存空間,能夠看作是當前線程執行的字節碼的行號指示器。理解就是虛擬機把java源代碼編譯成了字節碼,而後程序被執行,可是程序執行是須要順序的,何時該執行什麼代碼呢?就是靠這個程序計數器來實現的,字節碼解釋器在工做的時候會改變這個計數器的值,來選取下一條須要執行的字節碼指令。對象
特色:blog
(1)、每一個線程一個。你們知道,所謂的多線程事實上是把時間進行切片而後把細碎的時間無序的分配給多個線程使用,cpu在多個線程之間切換,看起來就像是多個線程同時執行。在頻繁的線程切換中藥保證每個線程在被執行的時候都可以正確的執行下一行代碼,就須要給每個線程分配一個獨立的程序計數器。因此程序計數器是在藍色區域,是每個線程都獨立擁有的,數據線程隔離。接口
(2)、由於是記錄一個虛擬機字節碼指令地址的,因此不會有內存溢出。內存
注意:若是線程執行的是一個java方法,這個計數器記錄的是正在執行的續集字節碼的指令地址,而若是正在執行的是一個Native方法,則計數器爲空。
Native方法:若是翻譯的話是翻譯成「本地方法」。理解的話就是一個java接口,可是它的實現不是使用java語言。詳細一點的介紹一篇博客: http://blog.csdn.net/wike163/article/details/6635321。
三、Java虛擬機棧:
用途:描述方法執行的內存模型,在該線程上,每個方法執行都會建立一個棧幀(一方法一棧幀),每個方法的調用到執行完成的過程就是一個棧幀在虛擬機中的入棧到出棧的過程。
特色:
(1)、Java虛擬機棧是線程私有的;
(2)、每個方法對應的棧幀主要用來存儲每個方法的局部變量表、操做數棧、動態連接、方法出口等信息(具體後面討論);
(3)、在通常意義理解上的內存管理分爲棧和堆,其中的棧指的是虛擬機棧中的棧幀中的局部變量表;
(4)、異常:
Stack Overflow異常:當請求的棧深度大於虛擬機所容許的棧深度出現;
OutOfMemoryError異常:當棧進行動態擴展,沒法申請到足夠的內存時出現;
(5)、棧幀的局部變量表須要的內存空間在編譯期間完成分配,而當方法運行的時候是不會發生改變的,這個和類同樣,類的對象須要的內存空間在類加載的時候就已經肯定,分配對象內存的時候不會發生改變。
四、本地方法棧:
用途:與java虛擬機棧相似,都是用來執行方法,區別是java虛擬機棧執行的是java方法,而本地方法棧執行的是Native方法。
特色:不是每一種java虛擬機都有本地方法棧,一些虛擬機中將它與java虛擬機合二爲一。
五、Java堆:
用途:存放類實例對象和數組;
特色:
(1)、全部運行時數據區最大的一塊,GC(垃圾收集管理器)的主場;
(2)、OutOfMemoryError異常:當堆中沒有內存能夠用來完成類實例的分配了,並且也沒有辦法再擴展大小的時候會出現OutOfMemoryError異常;
(3)、是全部線程共享的區域;
五、方法區(Method Area):
用途:用於存儲虛擬機加載的類信息、常量、靜態變量、即時編譯後的代碼等數據。(java虛擬機規範把方法區描述爲堆的一個邏輯部分,可是它是與堆不同的)
特色:
(1)、這個區域的垃圾回收是頗有必要的,雖然效率上是很低的。垃圾收集的對象主要是常量池的回收以及對類型的卸載。
(2)、異常:當方法區沒法知足內存分配需求的時候將出現OutOfMemoryError異常。
(3)、這個區域也是全部線程共享的。
六、運行時常量池:
用途:一個類在編譯的時候會生成各類字面量和符號引用,這部份內容在類加載時將會進入方法區的運行時常量池進行存放。
特色:
(1)、它是方法區的一部分(JDK1.6以後常量池被放入堆空間中);
(2)、具有動態性;上面說的運行時常量池是存放在類加載的時候產生的常量,可是在運行的時候其實也能夠把新的常量放入池中,如String 的intern方法;這個方法會把字符串放入運行時常量池中,並返回該字符串,做用是重用字符串,即當調用這個方法的時候會去運行池常量中檢查是否已經存在相同的字符串,如果,則指向該字符串,若不是,則把該字符串放入運行時常量池中並返回該字符串。
(3)、異常:當常量池沒法申請到內存時會拋出OutOfMemoryError異常。