方法區 (Method Area or Permanent Generation):java
線程共享的內存區域,用於存儲以被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。雖然這個區域被虛擬機規範把方法區描述爲堆的一個邏輯部分,可是它的別名叫NonHeap,用來與堆作區別,經過-XX:permSize和-XX:MaxPermSize設置該空間大小。當方法區沒法知足內存分配需求時就會拋OutOfMemoryError。數組
運行時常量池(Runtime Constant Pool):服務器
它是方法區的一部分。Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池(ConstantPool Table),用於存放編譯期生成的各類字面量和符號引用,這部份內容將在類加載後存放到方法區的運行時常量池中。Java虛擬機對Class文件的每一部分(天然也包括常量池)的格式都有嚴格的規定,每個字節用於存儲哪一種數據都必須符合規範上的要求,這樣纔會被虛擬機承認、裝載和執行。但對於運行時常量池,Java虛擬機規範沒有作任何細節的要求,不一樣的提供商實現的虛擬機能夠按照本身的須要來實現這個內存區域。不過,通常來講,除了保存Class文件中描述的符號引用外,還會把翻譯出來的直接引用也存儲在運行時常量池中。運行時常量池相對於Class文件常量池的另一個重要特徵是具有動態性,Java語言並不要求常量必定只能在編譯期產生,也就是並不是預置入Class文件中常量池的內容才能進入方法區運行時常量池,運行期間也可能將新的常量放入池中,這種特性被開發人員利用得比較多的即是String類的intern()方法。既然運行時常量池是方法區的一部分,天然會受到方法區內存的限制,當常量池沒法再申請到內存時會拋出OutOfMemoryError異常。數據結構
堆(Heap):ide
虛擬機管理的最大的一塊內存,同時也是被全部線程所共享的,它在虛擬機啓動時建立,存在的意義就是存放對象實例,幾乎全部的對象實例以及數組都要在這裏分配內存。這裏存放的對象被自動管理,也就是俗稱的GC(GarbageCollector)所管理。Java堆的容量能夠經過-Xmx和-Xms參數調整空間大小。堆所使用的內存不須要保證是物理連續的,只要邏輯上是連續的便可。若是堆中沒有可用內存完成實例分配而且堆也沒法擴展,這時就會拋OutOfMemoryError。函數
虛擬機棧(Virtual Machine Stack):性能
每個線程都有本身的虛擬機棧,這個棧與線程同時建立,它的生命週期與線程相同。虛擬機棧描述的是Java方法執行的內存模型:每一個方法被執行的時候都會同時建立一個棧幀(StackFrame)用於存儲局部變量表、操做數棧、動態連接、方法出口等信息。每個方法被調用直至執行完成的過程就對應着一個棧幀在虛擬機棧中從入棧到出棧的過程。JVM Stack能夠被實現成固定大小,也能夠根據計算動態擴展。若是採用固定大小的JVM Stack設計,那麼每一條線程的JVM Stack容量應該在線程建立時獨立地選定。JVM實現應該提供調節JVMStack初始容量的手段;若是採用動態擴展和收縮的JVM Stack方式,應該提供調節最大、最小容量的手段。若是線程請求的棧深度大於虛擬機所容許的深度將拋出StackOverflowError;若是JVMStack能夠動態擴展,可是在嘗試擴展時沒法申請到足夠的內存時拋出OutOfMemoryError,經過-Xss參數可設置棧大小。spa
本地方法棧(Native Method Stack):操作系統
本地方法棧與虛擬機棧做用類似,後者爲虛擬機執行Java方法服務,而前者爲虛擬機用到的Native方法服務。虛擬機規範對於本地方法棧中方法使用的語言,使用方式和數據結構沒有強制規定,甚至有的虛擬機(好比HotSpot)直接把兩者合二爲一。線程
程序計數器(Program Counter Register):
它是一塊較小的內存空間,它的做用是記錄當先線程所執行的字節碼的信號指示器。每一條JVM線程都有本身的PC寄存器,各條線程之間互不影響,獨立存儲,這類內存區域被稱爲「線程私有」內存在任意時刻,一條JVM線程只會執行一個方法的代碼。該方法稱爲該線程的當前方法(Current Method)若是該方法是java方法,那PC寄存器保存JVM正在執行的字節碼指令的地址。若是該方法是native,那PC寄存器的值是undefined。此內存區域是在Java虛擬機規範中惟一沒有規定OutOfMemoryError狀況出現的區域。
直接內存(Direct Memory):
直接內存(DirectMemory)並非虛擬機運行時數據區的一部分,也不是Java虛擬機規範中定義的內存區域,可是這部份內存也被頻繁地使用,並且也可能致使OutOfMemoryError異常出現。JDK1.4加的NIO中,ByteBuffer有個方法是allocateDirect(intcapacity) ,這是一種基於通道(Channel)與緩衝區(Buffer)的I/O方式,它可使用Native函數庫直接分配堆外內存,而後經過一個存儲在Java堆裏面的DirectByteBuffer對象做爲這塊內存的引用進行操做。這樣能在一些場景中顯著提升性能,由於避免了在Java堆和Native堆中來回複製數據。顯然,本機直接內存的分配不會受到Java堆大小的限制,可是,既然是內存,則確定仍是會受到本機總內存(包括RAM及SWAP區或者分頁文件)的大小及處理器尋址空間的限制。服務器管理員配置虛擬機參數時,通常會根據實際內存設置-Xmx等參數信息,但常常會忽略掉直接內存,使得各個內存區域的總和大於物理內存限制(包括物理上的和操做系統級的限制),從而致使動態擴展時出現OutOfMemoryError異常。