java虛擬機器在執行java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域
主要包括方法區、堆區、虛擬機器棧、本地方法棧、程式計數器
其中方法區和堆區為進程的所有子線程共用,其它的為線程專屬
程式計數器
程式計數器是一塊較小的記憶體空間,它的作用可以看作是當前線程所執行的位元組碼的行號指標。每個線程都有一個獨立的程式計數器,各條線程之間的計數器互不影響,隔離儲存區 (Isolated Storage),是線程私人記憶體
Java虛擬機器棧和本地方法棧
本地方法棧和虛擬機器棧所發揮的作用是非常相似的,區別是虛擬機器棧執行java方法,而本地方法棧則為虛擬機器使用的Native方法服務,在sun hotspot中已經把兩者合二為一了,本地方法棧區也會拋出StackOverFlowError和OutOfMemeoryError異常
Java堆
java堆是垃圾收集器管理的主要區域,因此很多時候也被稱為GC堆,Java堆是被所有線程共用的一塊記憶體地區,在虛擬機器啟動時建立。此地區的唯一目的就是存放對象執行個體,幾乎所有對象的執行個體都在這分配記憶體。
方法區
方法區和java堆一樣,是各個線程共用的記憶體地區,它用於儲存已被虛擬機器載入的類資訊,常量,靜態變數。即時編譯器編譯後的代碼等資料。
運行時常量池
運行時常量池是方法區的一部分。用於存放編譯器產生的各種字面量和符號引用,它同樣也受到方法去記憶體的限制,當常量池無法在申請到記憶體的時候會拋出OutOfMemoryError異常
直接記憶體
直接記憶體並不是虛擬機器運行時資料區的一部分,也不是虛擬機器規範中定義的記憶體地區。
OutOfMemoryErrot異常
java堆溢出
Java堆用於儲存對象執行個體,只要不斷建立對象,並且保證GC Roots到對象之間有可達路徑來避免記憶體回收機制清除這些對象,就會在對象數量達到最大堆的容量限制後產生記憶體溢出異常。
虛擬機器和本地方法棧溢出
運行時常量池溢出
如果要向運行時常量池新增內容,最簡單的方法就是使用String.intern()這個Native方法。該方法的作用是:如果池中已經包含了一個等於此String對象的字串,則返回代表池中這個字串的String對象;否則將此String對象包含的字串添加到常量池中,並且返回此String對象的引用。由於常量池分配在方法區,因此可以通過-XX:PermSize和-XX:MaxPermSize限制方法區大小間接限制其中常量池中的容量。
方法區溢出
本地直接記憶體溢出
DirectMemory容量可通過參數指定,如果不指定則預設和Java堆的最大值一樣