Java的記憶體區域劃分
記憶體分區簡介
老生常談的問題了,雖然網上一搜一大把,也很詳細,但是我還是想寫一寫,通過自己的總結整理,加深一下印象。
我不知道學習Java記憶體分區有什麼實際作用,但它就是像常識一樣,一個使用Java語言的人不知道記憶體分區總感覺差點意思。
Java程式是運行在JVM虛擬機上的。Java虛擬機在運行程式時會把其自動管理的記憶體劃分為以下幾個區域:
方法區、堆、程式計數器、虛擬機棧、本地方法棧。
其中方法區和堆是所有執行緒共享的,而程式計數器、虛擬機棧和本地方法棧是每個執行緒獨立享有的。
這個不需要死記硬背,當我們了解了這幾個區域不同的功能之後,就知道為什麼有些記憶體區域是執行緒共享,而另外一些是執行緒私有的了。
各區域職責劃分
方法區(Method Area)
方法區屬於執行緒共享的記憶體區域,《Java虛擬機規範》中將其描述為堆的一個邏輯部分,又稱Non-Heap(非堆,目的是與Java堆區分開來),主要用於存儲已被虛擬機載入的類型資訊、常量、靜態變數、即時編譯器編譯後的程式碼快取等數據。
拿做菜打個比方,我理解方法區就好比一個食譜,它裡面記錄著做菜需要用的食材,加工方式等等。既然是菜譜,那就是公共的東西,不能修改,沒必要每個執行緒都有一份,大家誰需要誰來查看就好了。所以它是執行緒共享的。
JVM堆(Java Heap)
Java 堆在虛擬機啟動時創建,是Java 虛擬機所管理的記憶體中最大的一塊,主要用於存放對象實例,幾乎所有的對象實例都在這裡分配記憶體,是垃圾收集器管理的主要區域,因此很多時候也被稱做GC 堆(Garbage Collection),如果在堆中沒有記憶體完成實例分配,並且堆也無法再擴展時,將會拋出OutOfMemoryError 異常。
這次有點牽強,但還是可以拿做菜打比方。
先說說面向對象。堆是用來存儲對象的,對象是什麼呢?對象是幫助我們做事情的東西,很多人拿洗衣服來說明面向對象編程。如果我們面向過程洗衣服,那麼我們需要揉搓、洗滌、擰水、晾曬,每一步都要親力親為;而當我們面向對象時,只需要將衣服扔進洗衣機這個對象,剩下的事就不用管了,輕鬆省力。所以對象,就是幫助我們做事的工具。
在做菜中,對象可以理解為電烤箱、菜刀,這種工具,那麼在程式中,堆就是用來存儲這些工具的,每個人都可以使用這些工具,不會亂套,所以堆也是執行緒共享的。
程式計數器(Program Counter Register):
程式計數器屬於執行緒私有的數據區域,是一小塊記憶體空間,主要代表當前執行緒所執行的位元組碼行號指示器。位元組碼解釋器工作時,通過改變這個計數器的值來選取下一條需要執行的位元組碼指令,分支、循環、跳轉、異常處理、執行緒恢復等基礎功能都需要依賴這個計數器來完成。
用做菜來說,程式計數器記錄的是你做菜做到了哪個環節了,顯然不可能每個廚師都恰好在做相同的事,大家需要自己把控自己的進度,所以程式計數器是執行緒私有的。
虛擬機棧(Java Virtual Machine Stacks):
屬於執行緒私有的數據區域,與執行緒同時創建,總數與執行緒關聯,代表Java方法執行的記憶體模型。每個方法執行時都會創建一個棧楨來存儲方法的的變數表、操作數棧、動態鏈接方法、返回值、返回地址等資訊。每個方法從調用直結束就對於一個棧楨在虛擬機棧中的入棧和出棧過程。
這個對應的就是做菜的過程了,比如做一道菜需要三步,準備材料→炒菜→出鍋。拿第一步舉例,首先要準備材料,準備材料這個方法就要入棧了,入棧後發現,需要先把菜洗了,那麼洗菜這個方法也要進棧,然後又發現需要先摘菜葉子。我們假定摘菜葉之前沒有其他操作了,那麼之後從棧頂開始先執行摘菜方法,然後摘菜方法彈出,然後執行洗菜方法,然後洗菜方法彈出,再執行準備材料方法,是一個後進先出的順序,前一個彈出,後一個再執行。既然都已經具體到過程了,自然每個執行緒是要隔離開的,不能相互干擾。
本地方法棧(Native Method Stacks):
本地方法棧跟 Java 虛擬機棧的功能類似,Java 虛擬機棧用於管理 Java函數的調用,而本地方法棧則用於管理本地方法的調用。但本地方法並不是 用 Java 實現的,而是由 C 語言實現的(比如Object.hashcode 方法)。 本地方法棧是和虛擬機棧非常相似的一個區域,它服務的對象是 native方法。你甚至可以認為虛擬機棧和本地方法棧是同一個區域。
虛擬機規範無強制規定,各版本虛擬機自由實現 ,HotSpot 直接把本地方法棧和虛擬機棧合二為一 。
本地方法棧屬於執行緒私有的數據區域,這部分主要與虛擬機用到的 Native 方法相關,一般情況下,我們無需關心此區域。
簡單總結一下
Java記憶體區域劃分為5個,重點關注的是堆、棧、和方法區,程式計數器與本地方法棧一般不大涉及到。
方法區與堆是所有執行緒共享的,其餘三個是每個執行緒私有的。
堆是兵器庫,垃圾回收的主要區域,方法區是指揮官,棧是管幹活的。
如果我的理解和表達有不對的地方,歡迎大佬們斧正。