案例解說JVM記憶體空間(建議收藏)
今天,跟大家一起聊聊關於JVM記憶體空間的話題,這也是一線網路大廠面試中常被問及的問題,建議小夥伴們收藏後常常拿出來翻閱,重在理解。好了,不多說了,開始今天的正題。
JVM會把記憶體分割成不同的資料區域,那載入的類別是分配到哪裡呢?
下圖是記憶體的各個區域,包括:方法區、堆疊、虛擬機器堆疊、本機方法堆疊、程式計數器。

方法區
#方法區用於儲存已被虛擬機載入的類別資訊、常數、靜態變數、即時編譯器編譯後的程式碼等資料。類別的載入中提到了類別載入的五個階段。在載入階段,會將位元組流所代表的靜態儲存結構轉換為方法區的執行時間資料結構,在準備階段,會將變數所使用的記憶體都會在方法區中進行分配。
程式計數器
#來一個簡單的程式碼,計算(1 2)*3並回傳
public int cal() { int a = 1; int b = 2; int c = 3; return (a + b) * c; }
這段程式碼在載入到虛擬機器的時候,就變成了以下的字節碼,虛擬機執行的時候,就會一行行執行。

java是多執行緒的,在執行緒切換回來後,它需要知道原先的執行位置在哪裡。用來記錄這個執行位置的,就是程式計數器,為了確保執行緒間的計數器互相不影響,這個記憶體區域是線程私有的。
虚拟机栈
虚拟机栈也是线程私有的,生命周期与线程相同。每个线程都有自己的虚拟机栈,如果这个线程执行了一个方法,就会创建一个栈帧,方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。比如下面的例子,fun1调用fun2,fun2调用fun3,fun3创建Hello对象。
public void fun1() { fun2(); } public void fun2() { fun3(); } public void fun3() { Hello hello = new Hello(); }
调用的时候,流程图如下:

执行完成的时候,流程图如下:

每一个栈帧都包括了局部变量表、操作数栈、动态连接、方法返回地址和一些额外的附加信息。局部变量主要是存放方法参数以及方法内部定义的局部变量,操作数栈是一个后入先出栈,当方法刚刚开始执行的时候,这个方法的操作数栈是空的,在方法的执行过程中,会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈/入栈操作。
我们通过上面(1+2)*3的例子,把方法区、程序计数器、虚拟机栈的协同工作理一下。首先通过javap查看它的字节码,经过类加载器加载后,此时这个字节码存在方法区中。stack表示栈深度是2,locals是本地变量的slot个数,args_size是入参的个数,默认是this。栈的深度、本地变量个数,入参个数,都是在编译器决定的。

如下图,指令的位置是方法区,局部变量和操作数栈的位置是虚拟机栈,程序计数器就在程序计数器(这个下面的图就不再重复)。当执行偏地址为0的指令的时候,程序计数器为0,局部变量第一个值是this,当前的指令就是方法区0:iconst_1
,指令iconst_1就是把int常量值1进栈,这个1就到了虚拟机栈的操作数栈中。

当执行偏地址为1的指令的时候,程序计数器为1,把操作数栈的值赋值到局部变量,此时操作数栈清空了,局部变量多了一个1,这条指令执行完,就是对应上面int a=1的语句。

另外b,c兩個語句的賦值,對應2,3,4,5指令,這邊不再重複。執行完5後,如下圖:

執行6的時候,是執行iload_1,就是把第二個int型局部變數壓入堆疊頂,這裡的變數是1。

執行7的時候,是執行iload_2,就是把第三個int型局部變數壓入堆疊頂,這裡的變數是2。

執行8的時候,是iadd語句,指的是棧頂的兩個int型元素出棧,得到結果後再壓入棧頂。

執行9的時候,把堆疊頂的元素3,賦值到第五個局部變數。

執行到11的時候,把第五個局部變數值壓入棧頂,執行到13的時候,把第四個局部變數值壓入棧頂,執行14的時候,棧頂的兩個int型元素出棧,相乘後的結果入棧,執行15的時候,從目前方法返回目前棧頂int型元素。這些與上面的相加差不多,就不再贅述了。
堆
堆記憶體區域的唯一目的就是要存放物件實例,幾乎所有的物件實例都在這裡分配記憶體。例如上面的fun1呼叫fun2,fun2呼叫fun3,fun3建立Hello物件。 fun3方法中建立物件時,就是在堆中創建的,並且把位址賦值給fun3的局部變數。 Java堆中還可細分為:新生代與老年代;新生代也細分為Eden空間、From Survivor空間、To Survivor空間。

總結
#整體流程如下,先把java文件編譯成class文件,透過類別載入器載入到方法區。執行緒呼叫方法的時候,會創建一個棧幀,讀取方法區的字節碼執行指令,執行指令的時候,會把執行的位置記錄在程式計數器中,如果創建對象,會在堆內存中創建,方法執行完,這個棧幀就會出棧。

#相關參數
#-XX:PermSize:永久代記憶體容量。
-XX:MaxPermSize:永久代最大記憶體容量。
-XX:MetaspaceSize :元空間初始值的大小
##-XX:MaxMetaspaceSize :元空間最大值大小-XX:CompressedClassSpaceSize :元空間中儲存Klass類元資料部分的空間大小-Xss:堆疊記憶體容量。 -Xms:堆記憶體容量。 -Xmx:堆疊最大記憶體容量,通常和-Xms設定一樣,防止執行時間擴容產生的影響。 -Xmn:新生代記憶體容量,老年代就是堆記憶體容量-新生代記憶體容量-XX:SurvivorRatio=8:新生代還細分為Eden空間、From Survivor空間、To Survivor空間,設定為8代表Eden空間:From Survivor空間:To Survivor空間=8:1:1,例如新生代有10M,那Eden空間佔8M,From Survivor空間、To Survivor空間各佔1M。
以上是案例解說JVM記憶體空間(建議收藏)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

該專案為了方便開發者更快監控多個遠端主機jvm,如果你的專案是Spring boot那麼很方便集成,jar包引入即可,不是Spring boot也不用氣餒,你可以快速自行初始化一個Spirng boot程式引入jar包即可

掌握JVM記憶體使用量的重點與注意事項JVM(JavaVirtualMachine)是Java應用程式運作的環境,其中最為重要的就是JVM的記憶體管理。合理地管理JVM記憶體不僅可以提高應用程式的效能,還可以避免記憶體洩漏和記憶體溢位等問題。本文將介紹JVM記憶體使用的要點和注意事項,並提供一些具體的程式碼範例。 JVM記憶體分區JVM記憶體主要分為以下區域:堆(He

透過JVM命令列參數,您可以細微地調整JVM行為。其中通用參數包括:設定Java堆大小(-Xms、-Xmx)設定新生代大小(-Xmn)啟用平行垃圾收集器(-XX:+UseParallelGC)減少Survivor區記憶體佔用(-XX:-ReduceSurvivorSetInMemory)消除冗餘餘垃圾回收(-XX:-EliminateRedundantGCs)列印垃圾回收資訊(-XX:+PrintGC)使用G1垃圾收集器(-XX:-UseG1GC)設定最大垃圾回收暫停時間(-XX:MaxGCPau

Java是一種流行的程式語言,在開發Java應用程式的過程中,可能會遇到JVM記憶體溢位錯誤。這種錯誤通常會導致應用程式崩潰,影響用戶體驗。本文將探討JVM記憶體溢位錯誤的原因和如何處理和避免這種錯誤。 JVM記憶體溢位錯誤是什麼? Java虛擬機器(JVM)是Java應用程式的運作環境。在JVM中,記憶體被分為多個區域,其中包括堆疊、方法區、堆疊等。堆是用於存儲創建的對象的

JVM虛擬機的作用及原理解析簡介:JVM(JavaVirtualMachine)虛擬機是Java程式語言的核心組成部分之一,它是Java的最大賣點之一。 JVM的作用是將Java原始碼編譯成字節碼,並負責執行這些字節碼。本文將介紹JVM的作用及其運作原理,並提供一些程式碼範例以幫助讀者更好地理解。作用:JVM的主要作用是解決了不同平台上Java程式的可移

JVM原理詳解:深入探究Java虛擬機的工作原理,需要具體程式碼範例一、引言隨著Java程式語言的快速發展和廣泛應用,Java虛擬機(JavaVirtualMachine,簡稱JVM)也成為了軟體開發中不可或缺的一部分。 JVM作為Java程式的運作環境,能夠提供跨平台的特性,使得Java程式能夠在不同的作業系統上運作。在本文中,我們將深入探討JVM的工作原

JVM記憶體參數設定:如何合理調整堆記憶體大小?在Java應用程式中,JVM是負責管理記憶體的關鍵元件。其中,堆記憶體是用來儲存物件實例的地方,堆記憶體的大小設定對應用程式的效能和穩定性有著重要影響。本文將介紹如何合理調整堆記憶體大小的方法,並附帶具體程式碼範例。首先,我們需要了解一些關於JVM記憶體的基礎知識。 JVM的記憶體分成了幾個區域,包括堆疊記憶體、堆疊記憶體、方法區等。其中

在寫java程式來檢查JVM是32位元還是64位元之前,我們先討論一下JVM。 JVM是java虛擬機,負責執行字節碼。它是Java執行時間環境(JRE)的一部分。我們都知道java是平台無關的,但是JVM是平台相關的。我們需要為每個作業系統提供單獨的JVM。如果我們有任何java原始碼的字節碼,由於JVM,我們可以輕鬆地在任何平台上運行它。 java檔案執行的整個過程如下-首先,我們保存擴展名為.java的java原始碼,編譯器將其轉換為擴展名為.class的字節碼。這發生在編譯時。現在,在運行時,J
