JVM中的五大內存區域劃分詳解及快速掃盲

2020-12-19 計算機java編程

一、快速掃盲

1. JVM是什麼

JVM是JavaVirtualMachine的縮寫,即咱們經常提到的Java虛擬機。虛擬機是一種抽象化的計算機,有著自己完善的硬體架構,如處理器、堆棧等,具體有什麼咱們不做了解。目前我們只需要知道想要運行Java文件,必須先通過一個叫javac的編譯器,將代碼編譯成class文件,然後通過JVM把class文件解釋成各個平臺可以識別的機器碼,最終實現跨平臺運行代碼。

2. JDK、JRE、JVM之間的關係

JDK:全稱為Java Development Kit,漢語為java開發工具包,即所有有關java的東西都包含在裡面,比如運行環境JRE、java的核心代碼、JVM等等。JRE:全稱為Java Runtime Environment,漢語為java運行環境,即想要運行java文件必須先有java的環境才行,jre就是提供了這麼一個環境。JVM:上面已經提到了JVM,它是java最核心的部分。簡單用一張圖來理解這三個的關係:

3. jvm的組成成分

不了解jvm的同學看到這張圖後可能會有點懵逼,不過沒關係,放這張圖只是想讓你了解jvm中有三塊內容非常重要,1.java代碼如何執行?2.內存如何管理?3.線程資源如何利用?腦袋裡有個印象即可,帶著問題去學習。

4. 運行java文件的大概流程

想要運行java的源文件,必須要經過javac編譯器編譯成.class文件,也就是字節碼文件。然後通過jvm中的解釋器,解釋成特定機器上的機器碼。每種機器上的解釋器是不一樣的,我們經常用的也就是windows和linux系統,這也是為什麼java能夠跨平臺的原因。當一個程序從開始運行,虛擬機就開始實例化,多個程序運行就會存在多個虛擬機實例,程序退出或者關閉,虛擬機實例也將隨之消亡,多個虛擬機之間的數據是不共享的。

二、JVM運行時數據區

1. 運行時數據區域組成

虛擬機在執行java程序時,會將自己管理的內存劃分為幾個區域,每個區域都有自己的用途,並且創建時間和銷毀時間也不一樣。在程序運行時的內存區域主要可以劃分為五個,分別是:方法區、堆、虛擬機棧、本地方法棧、程序計數器。可以用下面的圖來描述:

2. Java堆

Java堆是java虛擬機所管理的內存中最大的一塊,是被所有線程都共享的內存區域。存在的唯一目的就是存放對象實例,幾乎所有的對象實例都在這裡進行分配內存。不過目前隨著技術的不斷發展,也並不是所有的對象實例都在堆中分配內存,可能也存在棧上分配。由於所佔空間大,又存放各種實例對象,因此java虛擬機的垃圾回收機制主要管理的就是此區域,詳細的垃圾回收方法以後會提到。JVM規範中規定堆可以處於物理上不連續的內存空間中,只要邏輯上是連續的即可。並且可以通過-Xmx和-Xms來擴展堆的內存大小,如果在堆中沒有足夠的內存為實例分配,並且堆也無法在擴展時,就會報OutOfMemoryError異常。

3 方法區

跟Java堆一樣,方法區是各個線程共享的內存區域,此區域是用來存儲類的信息(類的名稱、欄位信息、方法信息)、靜態變量、常量以及編譯器編譯後的代碼。JVM規範中並不區分方法區和堆,只把方法區描述為堆的邏輯部分,但是它卻有一個別名叫做非堆(Non-Heap),目的就是與Java堆區分開。根據垃圾回收機制中分代回收的思想,如果在HotSpot虛擬機上開發,可以把方法區稱為「永久代」(只是可以這麼理解,但實質是不一樣的),垃圾回收機制在Java堆中劃分一個部分稱為永久代,用此區域來實現方法區,這樣HotSpot的垃圾收集器就可以像管理Java堆一樣管理這部分內存,而不必為方法區開發專門的內存管理器。

運行時常量池

運行時常量池是方法區的一個部分,class文件中除了有類的版本、欄位、方法、接口等描述信息外,還有一項信息是常量池,用於存放編譯期間生成的各種字面量和符號引用,這部分內容會在類加載後進入方法區的運行時常量池中。Java 虛擬機對 Class 文件的每一部分(自然也包括常量池)的格式都有嚴格的規定,每一個字節用於存儲哪種數據都必須符合規範上的要求,這樣才會被虛擬機認可、裝載和執行。

4. 程序計數器

雖然在上圖中程序計數器的面積很大,但實際上它是一塊較小的內存空間,可以看作當前線程所執行字節碼的行號指示器。字節碼解釋器在工作中時下一步該幹啥、到哪了,就是通過它來確定的。大家都知道在多線程的情況下,CPU在執行線程時是通過輪流切換線程實現的,也就是說一個CPU處理器(假設是單核)都只會執行一條線程中的指令,因此為了線程切換後能恢復到正確的執行位置,每個線程都要有一個獨立的程序計數器,各條線程之間的計數器互不影響,獨立存儲,我們稱這類內存區域為「線程私有」的內存。

很明顯,程序計數器就是線程私有的。如果線程正在執行的是一個java方法,程序計數器記錄的是正在執行的虛擬機字節碼指令地址;如果執行的Native方法,程序計數器記錄的值為空(Undefined),此內存區域是java中唯一一個在java虛擬機規範中沒有規定任何OutOfMemoryError情況的區域。

5. Java虛擬機棧

我們經常會把java內存粗糙的分為兩個部分,堆和棧,Java虛擬機棧就是棧這一部分,或者說是虛擬機棧中局部變量表部分。跟程序計數器一樣,虛擬機棧也是線程私有的,它的生命周期跟線程相同。每個方法在執行的同時都會創建一個棧幀(Stack Frame),每個棧幀對應一個被調用的方法,棧幀中用於存儲局部變量表、操作數棧、動態鍊表、方法出口等信息。每一個方法從開始執行到結束就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程。

局部變量表:顧名思義,他就是用來存儲方法中的局部變量(包括在方法中生命的非靜態變量以及函數形參),對於基本數據類型,直接存值,對於引用類型的變量,存儲指向該對象的引用。由於它只存放基本數據類型的變量、引用類型的地址和返回值的地址,這些類型所需空間大小已知且固定,所以當進入一個方法時,這個方法需要在棧幀中分配多大的局部變量空間是完全可以確定的,在方法運行期間也不會改變局部變量表的大小。指向運行常量池的引用:在方法執行過程中難免會使用到類中定義的常量,因此棧幀中要存放一個指向運行時常量池的引用。方法返回地址:當一個方法執行結束後,要返回到之前調用它的地方,因此在棧幀中需要保存一個方法返回地址。6. 本地方法棧

本地方法棧與虛擬機棧的功能非常的相似,區別不過是虛擬機棧為虛擬機執行java方法服務,而本地方法棧為虛擬機執行Native方法服務。有的虛擬機並不會區分本地方法棧和虛擬機棧,比如Sun HotSpot虛擬機直接將兩個合二為一。

7. 用一張圖總結

相關焦點

  • JVM內存區域之線程私有區域
    不過,也正是java把控制內存的權力交給了java虛擬機,一旦出現內存洩漏和內存溢出方面的問題,如果不了解虛擬機是怎麼使用內存的,那排查錯誤、修正問題將會成為一項異常艱難的工作。運行時數據區:java虛擬機在執行java程序的過程中會把它所管理的內存劃分為若干個不同的數據區域。
  • JVM 之內存結構的探索:究竟什麼是堆,什麼又是本地方法棧?
    接下來跟著我一探究竟上圖就是jvm比較詳細的內存劃分,下面我們來按線程私有共享來劃分jvm內存區下面我們來著重介紹一下這幾塊內存區域程序計數器(Program Counter Register)什麼是程序計數器呢,學過彙編的都知道,cs:ip
  • 2020第一篇:堆、棧、方法區、類加載器——JVM 內存模型分析
    在美好的祝願中,咱們開始今年的第一篇分享:JVM內存模型。JVM 內存模型看過上圖,應該對jvm有了一個大概的了解,如果沒看懂也不要緊,慢慢聽我來一一解釋圖中的這些組件:JVM內存劃分,是人為的根據不同內存空間的存儲特點以及存儲的數據而劃分的不同邏輯內存區域
  • 非洲的地理區域劃分,「東南西北中」五大區域該怎樣劃分?
    區域是研究地理問題的基本載體,我們所研究的自然或者人文地理問題,歸根到底實際上是在研究某一區域內的地理問題。當然,區域的範圍可大可小,也就是區域的尺度有大有小,地理區域的劃分方法有很多,包括政區、氣候、地形、自然帶、河流水系等等,都可以作為區域劃分的依據。
  • 程式設計師每日一題-jvm裡方法和方法區、棧區的二三事
    JAVA虛擬機運行時數據區的邏輯圖好,對照上圖,逐項解釋A:堆區是JVM 所管理的內存中最大的一塊。線程共享,主要是存放對象實例和數組。堆區是jvm裡面最需要深入研究的一塊區域,這裡面涉及內存分配,區域劃分,對象信息,垃圾回收。可以說如果java程式設計師對堆區不熟悉,那麼一定寫不出好的代碼。本文暫時不深入討論,後續會開專題深入講解。B:棧區,也叫虛擬機棧,顧名思義,它是一個棧,先進後出。它是線程創建時跟著創建,生命周期和線程一致,是線程私有的。
  • 一張圖讀懂jvm之運行時數據區-堆、棧、以及程序計數器
    比如,常量數據,臨時計算結果,你知道棧溢出和內存不足是怎麼一回事嗎?關注我,帶你一起走進 jvm,原創不易,記得關注 + 收藏哦。下面,我們來看下這張圖:運行時數據區分為:pc(program counter)寄存器、java 虛擬機棧、堆、方法區、運行時常量池、本地方法棧。
  • 重慶"五大功能區域"的物理隔離與化學反應
    重慶市委四屆三次全會立足重慶市情,綜合考慮人口、資源、環境、經濟、社會、文化等因素,將全市劃分為都市功能核心區、都市功能拓展區、城市發展新區、渝東北生態涵養發展區和渝東南生態保護發展區五大功能區域。
  • 花膠新手掃盲教程一:花膠檔次的劃分,記住了就不會花「大頭」錢
    這是一篇關於花膠新手的掃盲教程,業內人士請選擇性略過。花膠知識太專業,苦了廣大「吃膠群眾」近來小編感覺到關注花膠的朋友們越來越多。但是這又是如何劃分的呢?首先,花膠大致分為高、普、菜三個檔次,劃分的依據就是功效!功效!功效!
  • 系統內存佔用較高?
    那麼,現在得到一個初步的結論就是:不管是該jvm進程用到的堆內存還是堆外內存,都很小(相對於top命令顯式的18% * 8G佔用量而言)。所以是否可以猜想:jvm只是向作業系統申請了這麼多內存暫時沒有歸還回去,留待下次線程池有新任務時繼續復用呢?本文最後一部分試驗就圍繞著一點展開。
  • 習慣使用eclipse,如何快速上手IDEA?
    -XX:MaxMetaspaceSize: 元空間最大值,JDK8的永生代幾乎可用完機器的所有內存,為了保護伺服器不會因為內存佔用過大無法連接,需要設置一個初始值,和最大值保護一下。-Xss:在堆之外,線程佔用棧內存,默認每條線程為1M。存放方法調用出參入參的棧、局部變量、標量替換後的局部變量等,有人喜歡設小點節約內存開更多線程。但反正內存夠也就不必要設小,有人喜歡再設大點,特別是有JSON解析之類的遞歸調用時不能設太小。
  • 漳州「東西南北中」五大景觀區域總體策劃方案確定
    漳州「東西南北中」五大景觀區域總體策劃方案確定  恢復古八景 建環城生態休閒圈  閩南網12月29日訊 漳州市五大景觀區域總體策劃方案確定,目前,建設「東西南北中」五大景觀區域戰略部署已納入漳州市生態建設「七個五」行動計劃中。
  • 和平精英:新手快速掃盲攻略分享
    和平精英:新手快速掃盲攻略分享 新聞 178整編 ▪ 2020-12-08
  • 如何準確理解Java中的堆與棧
    關於內存可以說是Java中的重要概念,而棧和堆又是內存中的兩個重要部分。怎樣理解棧和堆?棧可以理解為內存中一片連續的區域,而堆可以理解為內存中一片分散的區域。可以說,棧是用來運行程序的區域,當在棧裡應用一個值的時候,這個值就會指向堆中的一個位置。其實可以理解為一種函數關係。
  • 詳解五種劃分四季的方法
    詳解五種劃分四季的方法 來源:SRC-563   發布時間:2013年02月25日16:53   通常來講,劃分四季主要有幾種方法
  • 蘋果序列號知識掃盲:iPhone序列號含義與查詢辨別真偽全攻略
    今天芝麻哥帶來一期蘋果序列號知識掃盲,一文帶你看懂序列號是什麼、如何查看序列號、蘋果序列號的含義、如何查詢序列號等等,相信對大家會有有所幫助。 iPhone 序列號是什麼? 1、首先通過前面的方法,複製好 iPhone 的 序列號 ,然後打開蘋果官網技術中心,找到「序列號查詢」頁面,然後粘貼上剛才複製的序列號,並輸入驗證碼,就可以快速查詢就可以了,如圖所示。
  • 1000人食堂廚房區域劃分標準
    宏量商廚1000人食堂廚房區域劃分必須嚴格按照標準執行,才能保障食堂廚房能有序的為1000人同時提供充足的食物而不會延遲,因此,合理的食堂廚房區域規劃能保障廚房運行的順暢。怎麼樣的規格才是1000人食堂廚房合理的區域劃分?
  • 曼谷區域詳解
    曼谷區域詳解 2020/5/23 12:54:38 智選海外房產 |
  • 《命運2》各星球淪陷區域位置詳解
    在《命運2》中,加入了一些新要素,比如「遺失區域」。