JVM運行時數據區域

来源:https://www.cnblogs.com/AganRun/archive/2019/11/23/11919101.html
-Advertisement-
Play Games

參考自《深入理解JAVA虛擬機》第二版 第2章 Java記憶體區域與記憶體溢出異常 2.1 概述 對於Java程式員來說,在虛擬機自動記憶體管理機制的幫助下,不再需要為每一個new操作去寫配對的delete/free代碼,由虛擬機管理記憶體這 一切看起來都很美好 ,一旦出現 記憶體泄漏和溢出方面 的問題,如果 ...


參考自《深入理解JAVA虛擬機》第二版

第2章 Java記憶體區域與記憶體溢出異常

2.1 概述

對於Java程式員來說,在虛擬機自動記憶體管理機制的幫助下,不再需要為每一個new操作去寫配對的delete/free代碼,由虛擬機管理記憶體這一切看起來都很美好,一旦出現記憶體泄漏和溢出方面的問題,如果不瞭解虛擬機是怎樣使用記憶體的,那麼排查錯誤將會成為一項異常艱難的工作。

2.2 運行時數據區域

Java虛擬機在執行Java程式的過程中會把它所管理的記憶體劃分為若幹個不同的數據區域。這些區域都有各自的用途。

image

2.2.1 程式計數器

程式計數器(Program Counter Register)是一塊較小的記憶體空間,它可以看作是當前線程所執行的位元組碼的行號指示器
在虛擬機的概念模型里,位元組碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的位元組碼指令,分支、迴圈、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器來完成。

由於Java虛擬機的多線程是通過線程輪流切換並分配處理器執行時間的方式來實現的,在任何一個確定的時刻,一個處理器都只會執行一條線程中的指令。因此,為了線程切換後能恢復到正確的執行位置,每條線程都需要有一個獨立的程式計數器,我們稱這類記憶體區域為線程私有的記憶體。

2.2.2 Java虛擬機棧

Java虛擬機棧(Java Virtual Machine Stacks)是線程私有的,它的生命周期與線程相同。

虛擬機棧描述的是Java方法執行的記憶體模型:每個方法在執行的同時都會創建一個棧幀用於存儲局部變數表、操作數棧、動態鏈接、方法出口等信息。每一個方法從調用直至執行完成的過程,就對應著一個棧幀在虛擬機棧中入棧到出棧的過程。

局部變數表存放了編譯期可知的各種基本數據類型對象引用returnAddress類型(指向了一條位元組碼指令的地址)。

其中64位長度的long和double類型的數據會占用2個局部變數空間(Slot),其餘的數據類型只占用1個。

局部變數表所需的記憶體空間在編譯期間完成分配。

對這個區域規定了兩種異常狀況:如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常;如果虛擬機棧可以動態擴展,如果擴展時無法申請到足夠的記憶體,就會拋出OutOfMemoryError異常。

2.2.3 本地方法棧

地方法棧(Native Method Stack)與虛擬機棧所發揮的作用是非常相似的,它們之間的區別不過是虛擬機棧為虛擬機執行Java方法(也就是位元組碼)服務,而本地方法棧則為虛擬機使用到的Native方法服務。

有的虛擬機(譬如Sun HotSpot虛擬機)直接就把本地方法棧和虛擬機棧合二為一。

本地方法棧區域也會拋出StackOverflowError和OutOfMemoryError異常。

2.2.4 Java堆

Java堆(Java Heap)是Java虛擬機所管理的記憶體中最大的一塊。Java堆是被所有線程共用的一塊記憶體區域。幾乎所有的對象實例都在這裡分配記憶體。

Java堆是垃圾收集器管理的主要區域,因此很多時候也被稱做“GC堆”。現在收集器基本都採用分代收集演算法,所以Java堆中還可以細分為:新生代和老年代;再細緻一點的有Eden空間、From Survivor空間、To Survivor空間等。

Java堆可以處於物理上不連續的記憶體空間中,只要邏輯上是連續的即可,就像我們的磁碟空間一樣。當前主流的虛擬機都是按照可擴展來實現的(通過-Xmx和-Xms控制)。如果在堆中沒有記憶體完成實例分配,並且堆也無法再擴展時,將會拋出OutOfMemoryError異常。

2.2.5 方法區

方法區(Method Area)與Java堆一樣,是各個線程共用的記憶體區域,它用於存儲已被虛擬機載入的類信息、常量、靜態變數、即時編譯器編譯後的代碼等數據。

對於習慣在HotSpot虛擬機上開發、部署程式的開發者來說,很多人都更願意把方法區稱為“永久代”(Permanent Generation),本質上兩者並不等價,僅僅是因為HotSpot虛擬機的設計團隊選擇把GC分代收集擴展至方法區,或者說使用永久代來實現方法區而已。

但使用永久代來實現方法區,現在看來並不是一個好主意,因為這樣更容易遇到記憶體溢出問題。已經發佈的JDK 1.7的HotSpot中,已經把原本放在永久代的字元串常量池移出。

相對而言,垃圾收集行為在這個區域是比較少出現的,但並非數據進入了方法區就如永久代的名字一樣“永久”存在了。這區域的記憶體回收目標主要是針對常量池的回收和對類型的卸載

2.2.6 運行時常量池

運行時常量池(Runtime Constant Pool)是方法區的一部分。Class文件中除了有類的版本、欄位、方法、介面等描述信息外,還有一項信息是常量池(Constant Pool Table),用於存放編譯期生成的各種字面量和符號引用,這部分內容將在類載入後進入方法區的運行時常量池中存放。

Java虛擬機對Class文件每一部分(自然也包括常量池)的格式都有嚴格規定,但對於運行時常量池,Java虛擬機規範沒有做任何細節的要求。

運行時常量池相對於Class文件常量池的另外一個重要特征是具備動態性,Java語言並不要求常量一定只有編譯期才能產生,也就是並非預置入Class文件中常量池的內容才能進入方法區運行時常量池,運行期間也可能將新的常量放入池中,這種特性被開發人員利用得比較多的便是String類的intern()方法。

既然運行時常量池是方法區的一部分,自然受到方法區記憶體的限制,當常量池無法再申請到記憶體時會拋出OutOfMemoryError異常。

2.2.7 直接記憶體

並不是虛擬機運行時數據區的一部分,也不是Java虛擬機規範中定義的記憶體區域。但是這部分記憶體也被頻繁地使用,而且也可能導致OutOfMemoryError異常出現。

在JDK 1.4中加入了NIO(New Input/Output)類,引入了一種基於通道(Channel)與緩衝區(Buffer)的I/O方式,它可以使用Native函數庫直接分配堆外記憶體,然後通過一個存儲在Java堆中的DirectByteBuffer對象作為這塊記憶體的引用進行操作。這樣能在一些場景中顯著提高性能,因為避免了在Java堆和Native堆中來回覆制數據。

伺服器管理員在配置虛擬機參數時,會根據實際記憶體設置-Xmx等參數信息,但經常忽略直接記憶體,使得各個記憶體區域總和大於物理記憶體限制。


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

-Advertisement-
Play Games
更多相關文章
  • 這是209.11.23的博客 下麵進入正題 Opencv的內容 各位都是大佬 HSV的顏色表和計算方法就不用說了吧 #include <opencv2/opencv.hpp> #include<iostream> #include<string> using namespace cv; using ...
  • 例17 百燈判亮 問題描述 有序號為1、2、3、…、99、100的100盞燈從左至右排成一橫行,且每盞燈各由一個拉線開關控制著,最初它們全呈關閉狀態。有100個小朋友,第1位走過來把凡是序號為1的倍數的電燈開關拉一下;接著第2位小朋友走過來,把凡是序號為2的倍數的電燈開關拉一下;第3位小朋友走過來, ...
  • SpringBoot讓你的Bean動起來(自定義參數解析HandlerMethodArgumentResolver) 簡介 我們 用到的一些 需要通過一定的方式去獲取的,可以通過註入方式獲取其他獲取方式進行獲取。 比如:需要用到用戶實例,我們通常做法為下 這樣是一般的做法,我們可以發現 可以通過註入 ...
  • 例16 巧解算式 問題描述 在1、2、3、4、5、6、7、8、9、10個數中間加上加號或減號,使得到的表達式的值為自然數N,如果中間沒有符號,則認為前後為一個數,如1 2 3認為是一百二十三(123)。 例如:當N=100時,表達式值為100的填法有24種。123+4+5+67-89-10=100是 ...
  • 參考:《深入理解JAVA虛擬機》第二版 3.3 垃圾收集演算法 由於垃圾收集演算法的實現涉及大量的程式細節,而且各個平臺的虛擬機操作記憶體的方法又各不相同,只是介紹幾種演算法的思想及其發展過程。 3.3.1 標記 清除演算法 最基礎的收集演算法是“標記 清除”(Mark Sweep)演算法。 演算法分為 標記和清除 ...
  • 在網上看到有關Redis的50道面試題,但是沒有給出答案,之前我也在尋找這份Redis面試題的答案,今天特地把答案分享出來。 花了大量時間整理了這套Redis面試題及答案,希望對大家有幫助哈~ 弄明白了這些Redis面試題基本上就可以成為面霸了,弔打面試官,哈哈~ 1、什麼是Redis? Redis ...
  • 面試實習生的時候,當問到 is 和 == 的區別時,很多同學都答不上來,搞不清兩者什麼時候返回一致,什麼時候返回不一致。本文我們來看一下這兩者的區別。 我們先來看幾個例子: a = "hello" b = "hello" print(a is b) # 輸出 True print(a == b) # ...
  • 慕課網 2019年11月23日 300套 資料下載 百度網盤 百度網盤下載地址: 鏈接:https://pan.baidu.com/s/1rqn-PjqSO_xC2WSx1os6MQ 提取碼:npre 複製這段內容後打開百度網盤手機App,操作更方便哦 微雲地址: https://share.wei ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...