Java虛擬機知識點【記憶體】

来源:https://www.cnblogs.com/bigshark/archive/2019/07/20/11219283.html
-Advertisement-
Play Games

運行時數據區   1. 程式計數器 (Program Counter)   每個線程獨占自己的程式計數器。如果當前執行的方式不是native的,那程式計數器保存JVM正在執行的位元組碼指令的地址,如果是native的,那程式計數器的值是undefined。 &e ...


運行時數據區

運行時數據區

  1.程式計數器(Program Counter)
  每個線程獨占自己的程式計數器。如果當前執行的方式不是native的,那程式計數器保存JVM正在執行的位元組碼指令的地址,如果是native的,那程式計數器的值是undefined。
  此記憶體區域是唯一一個在Java虛擬機規範中沒有規定任何OutOfMemoryError情況的區域。

  2.Java虛擬機棧
  每個線程獨占自己的Java虛擬機棧,這個棧與線程同時創建,用於存儲棧幀
  Java虛擬機棧所使用的記憶體不需要保證連續的。

  • StackOverflowError:線程請求分配的棧容量超過Java虛擬機棧允許的最大容量。
  • OutOfMemoryError:如果虛擬機棧可以動態擴展,在嘗試擴展的時候無法申請到足夠的記憶體,或者在創建新的線程時沒有足夠的記憶體去創建對應的虛擬機棧。

    3.Java堆
      Java堆可供各個線程共用,是給對象分配記憶體的區域,也是需要自動回收垃圾的區域。
      堆的容量可以是固定的,也可以隨著程式執行的需求動態擴展,併在不需要時自動收縮。Java堆所使用的記憶體不需要保證是連續的。
  • OutOfMemoryError:實際所需的堆超過了自動記憶體管理系統能提供的最大容量。
    4.方法區
      方法區可供各個線程共用。它存儲每一個類的結構信息,例如:運行時常量池、欄位和方法數據、構造函數和不同方法的位元組碼內容,還包括一些在類、實例、介面初始化時用到的特殊方法。
      方法區是Java堆的邏輯組成部分,虛擬機可以在這個區域不實現垃圾收集與壓縮。JVM規範也不限定實現方法區的記憶體位置和編譯代碼的管理策略。
      方法區容量可以是固定的,也可以隨著程式執行的需求動態擴展,併在不需要時自動收縮。方法區所使用的記憶體不需要保證是連續的。
  • OutOfMemoryError:方法區的記憶體空間不能滿足記憶體分配請求。

  關於永久代和元空間
  JDK 8引入了元空間的概念,它和JDK 8之前的永久代都是方法區的實現,區別是,永久代使用Java虛擬機記憶體,而元空間使用本地記憶體,將類的元數據移至元空間,而字元串和類靜態變數移至Java堆。

  引入元空間的主要原因有兩個

  • 永久代記憶體容易發生記憶體泄露,即java.lang.OutOfMemoryError: PermGen
  • 移除永久代可以促進HotSpot JVM與 JRockit VM的融合,因為JRockit沒有永久代。
    5.運行時常量池
      運行時常量池是class文件中每一個類或介面的常量池表的運行時表示形式。
      運行時常量池在方法區中分配,在載入類和介面到虛擬機後,就創建對應的運行時常量池。
  • OutOfMemoryError:方法區的記憶體空間不能滿足記憶體分配請求。
    6.本地方法棧
      JVM用本地方法棧來支持native方法。如果需要支持native方法,這個棧與線程同時創建。
  • StackOverflowError:線程請求分配的棧容量超過本地方法棧允許的最大容量。
  • OutOfMemoryError:如果本地方法棧可以動態擴展,在嘗試擴展的時候無法申請到足夠的記憶體,或者在創建新的線程時沒有足夠的記憶體去創建對應的本地方法棧。
    7.直接記憶體
      不是Java虛擬機規範定義的記憶體,不屬於運行時數據區,JDK NIO中基於通道與緩衝的I/O方式,可以直接分配堆外記憶體。直接記憶體受本機總記憶體的限制。
  • OutOfMemoryError:動態擴展導致總記憶體超過物理記憶體時。

    分配記憶體的兩種方式

  1. 指針碰撞:記憶體是絕對規整的,用過的記憶體和空閑的記憶體分別放在堆的兩邊,中間放著一個指針作為分界點的指示器,分配記憶體就是指針往空閑區域移動與對象大小相等的距離。
  2. 空閑列表:記憶體是不規整的,虛擬機維護一個列表,記錄哪些記憶體是可以使用的,分配記憶體就是從列表中找到一塊足夠大的記憶體劃分給對象實例。

選擇哪種分配方式由Java堆記憶體是否規整來決定,而Java堆是否規整又由所用的垃圾收集器是否帶有壓縮整理功能決定。因此,Serial、ParNew等帶壓縮過程的收集器採用指針碰撞,而CMS這種基於Mark-Swap演算法的收集器採用空閑列表。

如何保障分配記憶體時的線程安全性?

  1. 使用CAS技術保證操作的原子性。
  2. 每個線程在堆中預先分配一小塊記憶體稱本地線程分配緩衝(TLAB)。哪個線程要分配記憶體,就在哪個線程的TLAB上分配。當TLAB用完,分配新的TLAB時加鎖。

對象的記憶體佈局和訪問

  Java虛擬機在堆中給對象分配記憶體,對象在記憶體中的佈局分為三塊

  1. 對象頭:存儲了Mark Word、類型指針,如果是數組對象,還記錄了數據長度。
  2. 實例數據:對象的真實數據。
  3. 對齊填充:由於對象大小必須是8位元組的整數倍,所以需要占位符來對其填充。

 主流的對象訪問方式

  1. 使用句柄訪問:Java堆中劃分一塊記憶體作為句柄池,引用類型指向對象的句柄地址,句柄中包含對象實例數據與類型數據的地址。
  2. 使用直接指針訪問:引用類型指向對象地址,堆中存儲訪問類型數據的信息。

  Hotspot虛擬機使用直接指針的方式來訪問對象。節省了一次指針定位的時間開銷。

如下圖,展示了對象在記憶體的佈局和訪問方式。

對象的記憶體佈局

參考資料:《深入理解Java虛擬機(第二版)》《Java虛擬機規範(Java SE 8版)》


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

-Advertisement-
Play Games
更多相關文章
  •   Java虛擬機採用可達性分析演算法來判斷對象是否可以回收。可達性分析演算法通過一系列的GC Roots對象作為起始點,向下搜索走過的路徑稱引用鏈,當一個對象到GC Roots沒有任何的引用鏈時,證明對象是不可用的。 Java中,可作為GC Roots的對象: 虛擬機棧中引用的對象 ...
  • 第五章 簡單搜索 眾里尋他千百度 搜索是ES的核心,本節講解一些基本的簡單的搜索。 掌握ES搜索查詢的RESTful的API猶如掌握關係型資料庫的SQL語句,儘管Java客戶端API為我們不需要我們去實際編寫RESTful的API,但在生產環境中,免不了線上上執行查詢語句做數據統計供產品經理等使用。 ...
  • Spring中的JdbcTemplate JdbcTemplate:他是spring框架中提供的一個對象,是對原始Jdbc API對象的簡單封裝。 JdbcTemplate的作用:用於和資料庫交互的,實現對錶的CRUD操作 JdbcTemplate的入門 導入相關的坐標 賬戶實體類的建立 操作資料庫 ...
  • 1.學生類的使用: 結果: 2.手機類的使用: 結果: ...
  • 一、概述  前面的文章中提到,如果我們要調用其它應用的服務,只能夠通過 RestTemplate 的方式,這在我們實際的開發中很不方便。那麼有沒有類似於 Dubbo 中 @Reference 這樣的註解直接調用呢?這就是我們今天要講的 Spring Cloud Feign。  S ...
  • "Relative Sort Array" Example 1: Constraints: arr1.length, arr2.length include include using namespace std; class Solution { public: vector relativeSo ...
  • package model; /*22:37 2019/7/20*/ /* top class的修飾符組合 abstract final public 2 * 2 * 2 warning: abstract final 衝突 最終,共有2*(2*2-1)=6種修飾符組合用於top class */ ... ...
  • 1、包裝類簡介 我們都知道Java是面向對象編程語言,包含了8種基本數據類型,但是這8種基本數據類型並不支持面向對象的特征,它們既不是類,也不能調用方法。這在實際使用時存在很多的不便,比如int類型需要轉換成字元串,為瞭解決這個不足。然後就出現了包裝類,顧名思義,就是將這些基本數據類型封裝在類中,並 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...