這張圖我相信基本上對JVM有點接觸的都應該很熟悉,可以說這是JVM入門的第一課。其中的“堆疊”和“虛擬機器堆疊(堆疊)」更是耳熟能詳。下面將圍繞這張圖對JVM的運行時資料區做一個簡單介紹。
程式計數器(Program Counter Register)
## 這和電腦操作系統中的程式計數器類似,在電腦作業系統中程式計數器表示這個行程要執行的下個指令的位址,對於JVM中的程式計數器可以看做是目前執行緒所執行的字節碼的行號指示器,每個線程都有一個程式計數器(這很好理解,每個線程都有在執行任務,如果線程切換後要保證能恢復到正確的位置),重要的一點——程式計數器,這是JVM規格中唯一一個沒有規定會導致OutOfMemory# (記憶體洩露,下文簡稱OOM)的區域。換句話說上圖中的其餘4個區域,都有可能導致OOM。
☆虛擬機堆疊(Java Virtual Machine Stacks)
這塊記憶體區域就是我們常常說的“堆疊”,我們所熟知的是它用來存放變量,也就是說例如:
#int i = 0;虛擬機器棧記憶體就會用
4個位元組來儲存##i變數。對於變數的記憶體空間是一開始就能確定的(對於引用型變量,它當然儲存的就是一個位址引用,其大小也是固定),所以這塊記憶體區域在編譯器就能夠確定下來,這塊區域可能會拋出StackOverflowError或OOM錯誤。設定JVM參數」-Xss228k」(堆疊大小為228k)。
1 package com.jvm; 2 3 /** 4 * -Xss228k,虚拟机栈大小为228k 5 * Created by yulinfeng on 7/11/17. 6 */ 7 public class Test { 8 private static int count = 0; 9 10 public static void main(String[] args) {11 Test test = new Test();12 test.test();13 }14 15 /**16 * 递归调用17 */18 private void test() {19 try {20 count++;21 test();22 } catch (Throwable e) { //Exception已经捕获不了JVM抛出的StackOverflowError23 System.out.println("递归调用次数" + count);24 e.printStackTrace();25 }26 }27 }
這是一段沒有終止條件的遞歸,執行結果如下圖所示,JVM拋出StackOverflowError#表示執行緒請求的堆疊深度大於JVM所允許的深度。
對於單一執行緒情況下,無論如何拋出的都是StackOverflowError。如果要拋出OOM異常,導致的原因是不斷地在建立線程,直到記憶體消耗殆盡。
JVM的記憶體由堆內存 #+ 方法區內存 + 剩餘內存,也就是剩餘記憶體=作業系統分配給JVM#的記憶體 - 堆記憶體 - 方法區記憶體。 -Xss設定的是每個執行緒的堆疊容量,也就是說可以建立的執行緒數量 = 剩餘記憶體 / 堆疊記憶體。此時如果棧記憶體越大,可以建立的執行緒數量就少,就容易出現OOM#;如果堆疊記憶體越小,可以建立的執行緒數量就多,就不容易出現OOM。
要避免這種情況最好就是減少堆疊記憶體+方法區內存,或是適當地減少堆疊記憶體。對於堆疊記憶體的配置,一般採用預設值1M#,或採用64位元作業系統以及64 位元的JVM。
本機方法堆疊(Native Method Stack)
本機方法堆疊和虛擬機器堆疊類似,不同的是虛擬機器堆疊服務的是Java方法,而本機方法堆疊服務的是Native方法。在HotSpot虛擬機器實作中是把本機方法堆疊和虛擬機器堆疊合而為一的,同理它也會拋出StackOverflowError 和OOM異常。
☆Java堆(Java Heap)
########################################对于堆,Java程序员都知道对象实例以及数组内存都要在堆上分配。堆不再被线程所独有而是共享的一块区域,它的确是用来存放对象实例,也是垃圾回收GC的主要区域。实际上它还能细分为:新生代(Young Generation)、老年代(Old Generation)。对于新生代又分为Eden空间、From Survivor空间、To Survivor空间。至于为什么这么分,这涉及JVM的垃圾回收机制,在这里不做叙述。堆同样会抛出OOM异常,下面例子设置JVM参数” -Xms20M -Xmx20M“(前者表示初始堆大小20M,后者表示最大堆大小20M)。
1 package com.jvm; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * -Xms20M -Xmx20M 堆初始大小20M 堆最大大小20M 8 * Created by yulinfeng on 7/11/17. 9 */10 public class Test {11 12 public static void main(String[] args) {13 List<test> list = new ArrayList<test>();14 int count = 0;15 try {16 while (true) {17 count++;18 list.add(new Test()); //不断创建线程19 }20 } catch (Throwable e) {21 System.out.println("创建实例个数:" + count);22 e.printStackTrace();23 }24 25 }26 }</test></test>
执行的结果可以清楚地看到堆上的内存空间溢出了。
☆方法区(Method Area)
对于JVM的方法区,可能听得最多的是另外一个说法——永久代(Permanent Generation),呼应堆的新生代和老年代。方法区和堆的划分是JVM规范的定义,而不同虚拟机有不同实现,对于Hotspot虚拟机来说,将方法区纳入GC管理范围,这样就不必单独管理方法区的内存,所以就有了”永久代“这么一说。方法区和操作系统进程的正文段(Text Segment)的作用非常类似,它存储的是已被虚拟机加载的类信息、常量(从JDK7开始已经移至堆内存中)、静态变量等数据。现设置JVM参数为”-XX:MaxPermSize=20M”(方法区最大内存为20M)。
1 package com.jvm; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * -XX:MaxPermSize=20M 方法区最大大小20M 8 * Created by yulinfeng on 7/11/17. 9 */10 public class Test {11 12 public static void main(String[] args) {13 List<string> list = new ArrayList<string>();14 int i = 0;15 while (true) {16 list.add(String.valueOf(i++).intern()); //不断创建线程17 }18 }19 }</string></string>
其實對於上述程式碼,在JDK6、JDK7、JDK8運行結果均不一樣。原因就在於字串常數池在JDK6的時候還是存放在方法區(永久代)所以它會拋出OutOfMemoryError:Permanent Space#;而JDK7後則將字串常數池移到了Java堆中,上面的程式碼不會拋出OOM,將堆記憶體改為20M則會拋出OutOfMemoryError:Java heap space #;至於JDK8則是純粹取消了方法區這個概念,取而代之的是」#元空間(Metaspace)「,所以在JDK8中虛擬機器參數”-XX:MaxPermSize”也就沒有了任何意義,取代它的是”-XX:MetaspaceSize“#和” -XX:MaxMetaspaceSize”等。
以上是JVM基礎入門之運行時資料區的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JVM通過字節碼解釋、平台無關的API和動態類加載實現Java的WORA特性:1.字節碼被解釋為機器碼,確保跨平台運行;2.標準API抽像操作系統差異;3.類在運行時動態加載,保證一致性。

Java的最新版本通過JVM優化、標準庫改進和第三方庫支持有效解決平台特定問題。 1)JVM優化,如Java11的ZGC提升了垃圾回收性能。 2)標準庫改進,如Java9的模塊系統減少平台相關問題。 3)第三方庫提供平台優化版本,如OpenCV。

JVM的字節碼驗證過程包括四個關鍵步驟:1)檢查類文件格式是否符合規範,2)驗證字節碼指令的有效性和正確性,3)進行數據流分析確保類型安全,4)平衡驗證的徹底性與性能。通過這些步驟,JVM確保只有安全、正確的字節碼被執行,從而保護程序的完整性和安全性。

Java'splatFormIndepentEncealLowsApplicationStorunonAnyOperatingsystemwithajvm.1)singleCodeBase:writeandeandcompileonceforallplatforms.2)easileupdates:updatebybytecodeforsimultanane deployment.3)testOnOneOnePlatForforurouniverSalpeforuluniverSalpehavior formafforulululyiversalivernave.444.44.444

Java的平台獨立性通過JVM、JIT編譯、標準化、泛型、lambda表達式和ProjectPanama等技術不斷增強。自1990年代以來,Java從基本的JVM演進到高性能的現代JVM,確保了代碼在不同平台的一致性和高效性。

Java如何緩解平台特定的問題? Java通過JVM和標準庫來實現平台無關性。 1)使用字節碼和JVM抽像操作系統差異;2)標準庫提供跨平台API,如Paths類處理文件路徑,Charset類處理字符編碼;3)實際項目中使用配置文件和多平台測試來優化和調試。

java'splatformentenceenhancesenhancesmicroservicesharchitecture byferingDeploymentFlexible,一致性,可伸縮性和便攜性。 1)DeploymentFlexibilityAllowsibilityAllowsOllowsOllowSorlowsOllowsOllowsOllowSeStorunonAnyPlatformwithajvM.2)penterencyCrossServAccAcrossServAcrossServiCessImplifififiesDeevelopmentandeDe

GraalVM通過三種方式增強了Java的平台獨立性:1.跨語言互操作,允許Java與其他語言無縫互操作;2.獨立的運行時環境,通過GraalVMNativeImage將Java程序編譯成本地可執行文件;3.性能優化,Graal編譯器生成高效的機器碼,提升Java程序的性能和一致性。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Atom編輯器mac版下載
最受歡迎的的開源編輯器

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中