JVM入門——運行時數據區

来源:http://www.cnblogs.com/yulinfeng/archive/2017/07/12/7153391.html
-Advertisement-
Play Games

這張圖我相信基本上對JVM有點接觸的都應該很熟悉,可以說這是JVM入門的第一課。其中的“堆”和“虛擬機棧(棧)”更是耳熟能詳。下麵將圍繞這張圖對JVM的運行時數據區做一個簡單介紹。 程式計數器(Program Counter Register) 這和電腦操作系統中的程式計數器類似,在電腦操作系統 ...


jdk1.7.0_79 

  這張圖我相信基本上對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拋出的StackOverflowError
23             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虛擬機實現中是把本地方法棧和虛擬機棧合二為一的,同理它也會拋出StackOverflowErrorOOM異常。

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 }

  執行的結果可以清楚地看到堆上的記憶體空間溢出了。

方法區(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 }

  實際上對於以上代碼,在JDK6JDK7JDK8運行結果均不一樣。原因就在於字元串常量池在JDK6的時候還是存放在方法區(永久代)所以它會拋出OutOfMemoryError:Permanent Space;而JDK7後則將字元串常量池移到了Java堆中,上面的代碼不會拋出OOM,若將堆記憶體改為20M則會拋出OutOfMemoryError:Java heap space;至於JDK8則是純粹取消了方法區這個概念,取而代之的是元空間(Metaspace,所以在JDK8中虛擬機參數”-XX:MaxPermSize”也就沒有了任何意義,取代它的是”-XX:MetaspaceSize“”-XX:MaxMetaspaceSize”等。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 簡要說明:nginx的簡介自行百度。 目的:把用戶的請求分到各個伺服器減輕壓力。nginx把監聽的埠的請求平均轉到佈署了網站的伺服器。 一、windows上安裝nginx 1.官網下載windows版的nginx http://nginx.org/en/docs/windows.html 目前最新 ...
  • MD5的簡介:MD5即Message-Digest Algorithm 5(信息-摘要演算法5),用於確保信息傳輸完整一致。是電腦廣泛使用的雜湊演算法之一(又譯摘要演算法、哈希演算法),主流編程語言普遍已有MD5實現。將數據(如漢字)運算為另一固定長度值,是雜湊演算法的基礎原理,MD5的前身有MD2、MD3 ...
  • 我們今天簡要介紹RS指令在狀態機中怎麼處理的。有些設備按下停止按鈕後,沒有馬上停止,而是到原點後才停止,那麼這種情況在狀態機中如何表示呢?我們以案例說明之,下麵是我們的控制描述。控制描述小車從左位開始,從左向右行使,到達右位後停5秒,然後從右向左運行,到達左位後停3s,繼續向右運行。當按下停止按鈕後... ...
  • 首先有一個html頁面,頁面有一個鏈接,點擊鏈接彈出文件下載/保存(類似迅雷下載鏈接) <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title> ...
  • 在使用Html+ashx處理文件上傳時,遇到上傳文件超過4M的問題,首先HTML代碼如下: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <titl ...
  • Visual Studio提示“無法啟動IIS Express Web伺服器”的解決方法 有時,在使用Visual Studio運行ASP.NET項目時,會提示“無法啟動IIS Express Web伺服器”,無法運行,如圖: 這一般出現在重裝系統之後,或者項目是從別的電腦上複製過來的。解決方法就是 ...
  • 在Tomcat中主要有以下幾種類載入器:(圖片來自網路) tomcat啟動時,會創建幾種類載入器: 1 Bootstrap 引導類載入器 載入JVM啟動所需的類,以及標準擴展類,位於jre/lib/ext下。 2 System 系統類載入器 載入tomcat啟動的類,比如bootstrap.jar, ...
  • 前言 本文主要是筆者小結 WWDC2017 中 "《What's New in Swift》" 的 Session ,其中也摻雜了些《What’s New in Foundation》,僅作記錄。 下麵步入主題。 私有訪問控制("Private" Access Control) "SE 0169" ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...