Java虛擬機在執行Java程序中會把它所管理的內存劃分爲若干個數據區域,這些區域有各自的用途,以及生命週期,有些依賴虛擬機進程啓動而存在,有些依賴用戶線程的啓動和結束而創建和銷燬算法
程序計數器是一塊較小的內存空間,能夠看做是當前線程所執行的字節碼的指示器,字節碼解釋器經過改變這個計數器的值來選取下一條須要執行的字節碼指令。
因爲Java虛擬機的多線程是經過線程調度(輪詢)切換分配處理器執行時間的方式來實現的,在任何一個肯定的時刻都只會執行一條線程中的指令。因此爲了當線程切換後能找到以前執行指令的位置,每一個線程都須要有一個獨立的程序計數器,各個線程之間的程序計數器互相不影響,這類內存區域爲「線程私有」的內存區域。多線程
Java虛擬機棧和程序計數器同樣,Java虛擬機棧(如下簡稱棧)也是「線程私有」的,它的生命週期和線程相同,每一個方法在執行時都會建立一個棧幀(Stack Frame)用於存儲局部變量表(方法中定義的變量),操做數棧,動態連接,方法出口等信息。每一個方法從調用直至執行完成的過程,就是對應着一個棧幀在棧中入棧和出棧的過程。函數
本地方法棧和Java虛擬機棧同樣,本地方法棧用於執行Native方法spa
Java堆是被全部線程共享的一塊內存區域,在虛擬機啓動時被建立。此內存區域的惟一目的就是存放對象的實例,幾乎全部的對象實例都在這裏分配內存,Java堆是垃圾收集器管理的主要區域,因爲如今不少收集器都採用分代收集算法,全部Java堆還能夠細分爲:新生代和老年代。能夠經過-Xmx和-Xms來控制堆內存的大小線程
方法區和Java堆同樣,也是各個線程共享的內存區域,它用於存儲已經被虛擬機加載的類信息,常量,靜態變量,即時編譯器編譯後的代碼等數據。通常也稱做爲「永代區」(Permanent Generation),這裏要特別說明一下,由於咱們使用的主流虛擬機HotSpot的設計團隊用「永代區」來實現方法區,這樣HotSpot的垃圾收集器就能夠像管理堆那樣管理這部份內存,在JDK1.7的HotSpot中,已經把字符串常量池移出「永代區」了。設計
直接內存並非虛擬機運行時數據區的一部分,可是若是你使用了NIO的類,就會致使OutOfMemoryError異常出現
NIO引入了一種基於通道(Channle)與緩衝區(Buffer)的I/O方法,它可使用Native函數庫直接分配堆外的內存,而後經過一個存儲在Java堆中的DirectByteBuffer對象做爲這塊內存的引用進行操做。這樣能避免在Java堆和Native堆中來回複製數據的開銷,本機直接內存的分配不會受到Java堆大小的限制,可是會受到物理內存的限制,全部也會拋出OutOfMemoryError異常。對象
「程序計數器」和「Java虛擬機棧」是線程私有的,而「Java堆」和「方法區」是線程共享的生命週期
除了虛擬機運行時內存,在Java中使用NIO類能夠直接操做本機內存。進程
方法區在HotSpot中用於存放各類「常量信息」內存
Java堆中存放了程序中全部的對象實例