JVM內存區域

參考:深入理解Java虛擬機(第2版)

簡單概述JVM有哪些內存區域,以及他們的功能

主要是七個區域:

  1. 程序計數器
  2. Java虛擬機棧
  3. 本地方法棧
  4. Java堆
  5. 方法區
  6. 運行時常量池
  7. 直接內存

1.程序計數器

程序計數器是一塊較小的內存區域,我們可以將它看作是一個記錄當前代碼運行到什麼位置的行號指示器。
但是這個指示器並不是直接指定某行代碼,而是將Java文件編譯後的class文件,也就是字節碼文件(十六進制),是記錄字節碼執行到哪一行。所以字節碼解釋器工作時,就是通過改變這個計數器的值來選取下一條需要被執行的字節碼指令。分支循環跳轉異常什麼的,都靠這個計數器來完成。
每一個線程都有一個屬於自己的程序計數器,各個線程的計數器互不影響,獨立存儲。但如果當前執行的是native方法,這個計數器則爲空。此內存區域是唯一一個在Java虛擬機規範中沒有規定任何OutOfMemoryError情況的區域。

2.Java虛擬機棧

這個東西也是線程私有的東西。每個線程在執行的時候,都會創建一個棧幀,這個東西主要用來存儲局部變量表
、操作數棧、動態鏈接、方法出口等信息。每一個方法從調用直至執行完成的過程,就對應着一個棧幀在虛擬機棧中從入棧到出棧的過程

棧幀裏面的局部變量表存放的都是一些編譯期可知的各種基本數據類型,boolean、byte、int啥的,對象引用和returnAddress類型(指向一條字節碼指令的地址)。如果線程請求的棧深度大於虛擬機所允許的深度,就會拋StackOverflowError異常。如果虛擬機棧可以動態擴展,知道無法繼續擴展爲止都滿足不了線程請求的棧深度,那麼就會拋OutOfMemoryError異常。

3.本地方法棧

這玩意兒跟Java虛擬機棧差不多,區別就是本地方法棧是爲native方法工作的,不過現在有很多虛擬機把本地方法棧和虛擬機棧合二爲一了。

4.Java堆

這東西是Java虛擬機所管理的內存中最大的一塊,而且這個東西是被所有線程共享的。這個內存區域唯一的目的就是存放對象實例和數組,幾乎所有的對象實例都要在這裏分配內存。由於這個區域很大,所有我們著名的垃圾回收,主要管理的區域就是這個區域。如果這個區域的東西填滿了,也會拋出OutOfMemoryError異常。

5.方法區

跟Java堆一樣,也是一個各個線程共享的內存區域,主要存儲被虛擬機加載的類的信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。他還有一個別名(Non-Heap)非堆,估計是跟Java堆做區分。這個也是內存不夠的時候會拋出OutOfMemoryError異常。

6.常量運行池

這的區域其實是方法區的一部分,聽名字就能猜到主要是存放編譯期生成的各種字面量和符號引用。不一定是在編譯器,就把所有的常量放進來,在運行期間也可以把新的常量放到池中,比如使用String的intern()方法。這是方法區的一部分,所以內存不夠的時候也會拋出OutOfMemoryError異常

7.直接內存

老實說直接內存並不是虛擬機運行時數據區的一部分,也不是Java虛擬機規範中定義的內存區域。但這部分內存被頻繁使用,而且也會導致OutOfMemoryError異常出現,所以我們放到這裏一起講解。
JDK1.4有個NIO類,引入一種基於通道與緩衝區的IO方式,它可以使用native函數庫直接分配堆外內存,所以直接內存不會受到Java堆大小的限制,但既然是內存,還是會受到本機總內存的大小以及處理器尋址空間的限制。所有還是會出現OutOfMemoryError異常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章