深入理解Java虛擬機02--Java記憶體區域與記憶體溢出異常

来源:https://www.cnblogs.com/ganchuanpu/archive/2018/08/06/9428688.html
-Advertisement-
Play Games

一.概述 我們在進行 Java 開發的時候,很少關心 Java 的記憶體分配等等,因為這些活都讓 JVM 給我們做了。不僅自動給我們分配記憶體,還有自動的回收無需再占用的記憶體空間,以騰出記憶體供其他人使用。但是我們經常面臨的一個問題就是記憶體泄漏,JVM無法完成回收工作,導致記憶體占用暴漲,最後可能讓程式奔潰 ...


一.概述

  我們在進行 Java 開發的時候,很少關心 Java 的記憶體分配等等,因為這些活都讓 JVM 給我們做了。不僅自動給我們分配記憶體,還有自動的回收無需再占用的記憶體空間,以騰出記憶體供其他人使用。但是我們經常面臨的一個問題就是記憶體泄漏,JVM無法完成回收工作,導致記憶體占用暴漲,最後可能讓程式奔潰。本章主要瞭解下運行時數據區域分佈情況以及溢出異常。

二.運行時數據區域

1、程式計數器

  • 線程私有
  • 當前線程所執行的位元組碼的行號指示器
  • Java 多線程是通過再一個內核中輪流執行實現的,計數器就保證了切換線程的時候可以回到原來正確的執行位置
  • 程式計數器必須每個線程單獨一個,是線程私有的記憶體區域
  • 程式計數器是唯一一個 JVM 沒有規範 OutOfMemoryError 的區域

2、Java虛擬機棧(java方法)

  • 線程私有
  • Java方法執行的記憶體模型,即方法執行時會創建一個棧幀,保存了需要的局部變數表、操作數棧、動態鏈接、方法出口等信息;
  • 線程請求的棧深度>JVM允許的深度時,報StackOverflowError;
  • 大多數的 JVM 可以動態擴展記憶體,如果無法申請到足夠的記憶體時,報 OutOfMemoryError;

3、本地方法棧(native方法)

  • 同Java虛擬機棧

4、Java堆

  • 線程共用
  • 唯一目的:存放對象實例
  • 分類:新生代、老生代,或者 Eden 空間、From Survior 空間、To Survivor 空間
  • 分類目的:更好的回收和分配記憶體
  • 沒有記憶體完成實例分配,或者不能再擴展,報OutOfMemoryError 異常
  • 可以自己配置大小(-Xmx和-Xms)

5、方法區

  • 線程共用
  • 目的:存儲類信息、常量、靜態變數、即時編譯器編譯後的代碼等數據;
  • 該區記憶體回收目標:主要針對常量池的回收和對類型的卸載;
  • 無法滿足記憶體分配要求時,報 OutOfMemoryError 異常

6、運行時常量池

  • 註意:運行時常量池屬於方法區
  • 目的:存儲編譯期生成的各種字面量和符號引用
  • 特征:並非只有編譯期置入 Class 文件中的常量池內容才能進入運行時常量池,在運行期間也可以置入新的常量,比如 String 的intern() 方法;
  • 無法申請足夠記憶體時,報 OutOfMemoryError 異常

 

三.直接記憶體

  • 非運行時數據區域記憶體
  • Native 函數分配堆外記憶體,堆內的 DirectByteBuffer 作為這塊記憶體的引用
  • 性能顯著提高,避免了 Java 堆和 native 之間來回覆制數據

四.HotSpot虛擬機對象探秘

1、New對象過程

  • new 指令發出
  • 檢查 new 的參數是否在常量池中存在這個 Class 的符號引用
  • 檢查對應的 Class 是否已經初始化
  1. 若沒有則先執行初始化過程
  • 分配記憶體,檢查堆是否規整(垃圾收集器是否帶有壓縮整理功能決定)
  1. 規整:指針碰撞方式分配記憶體
  2. 不規整:空閑列表方式分配記憶體
  • 記憶體空間初始化為零值(不包括對象頭)
  • 對對象進行重要的配置
  • 執行 < init > 方法


2、對象的記憶體佈局

對象頭(Mark Word)

  • 自身運行時數據
  1. GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID
  2. 類型指針:確定對象是哪個Class的實例

實例數據

  • 存儲有效信息,定義的各種欄位
  • 相同寬度的欄位總是被分配到一起

對齊填充

  • 不一定存在
  • 實例數據沒有對齊,需要填充


3、對象的訪問定位
句柄(reference):

  • 堆中劃分句柄池
  • 句柄地址
  1. 到對象實例數據的地址
  2. 到對象類型的地址
  • 優勢:穩定,對象移動時,(如GC時會移動),這個時候只改變指針地址。句柄信息不變,相對穩定;

指針:

  • 直接存儲了上述的對象地址
  • 優勢:速度快

五.OOM

  • 堆溢出:舉例一直 new 新的實例對象
  • 棧溢出:舉例無限迴圈調用執行某個方法
  • 方法區和運行時常量池溢出:
  1. String.intern():如果常量池已存在,則返回 String 對象,如果不存在,則先添加到常量池,再返回 String 對象。
  2. 動態定義大量的 Class,需要註意記憶體的回收情況。

 


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

-Advertisement-
Play Games
更多相關文章
  • activity的生命周期 activity的四種狀態 running: 正在運行,處於活動狀態,用戶可以點擊屏幕,是將 處於棧頂的狀態。 paused: 暫停,處於失去焦點的時候,處於 ,可能是被如彈框一樣遮蓋,被通明的 的放置到棧頂, 一起狀態都存在。 stopped: 處於 狀態,是當前的 被 ...
  • 引言 在《iPhone User Guide for iOS 11.4》這本書中,介紹了iOS11的新特性。其中在Safari的章節中,介紹了Fill in forms。也就是當你在網頁登錄、註冊以及購買的時候,用戶可以通過鍵盤來填充網頁的表單、或者是Safari自己填充(前提是你開啟了AutoFi ...
  • 環信EaseUI 集成,集成不做描述,看文檔即可,下麵主要談一些對easeui的個性化需求修改。 一、如何將App用戶體系的用戶名和用戶頭像 顯示於環信的easeui 這個問題是所有人都想解決的,集成easeui之後 ,雖然大部分功能給我們做好了,但是他是顯示的環信用戶體系的用戶名和預設的頭像。 這 ...
  • 一.前言 我們一定心裡有個疑問,我們那個多態是怎麼回事?我們指定的一個介面,卻可以等到運行時可以對應於不同的實現類。這是因為,Java有個特性就是依賴運行期動態載入和動態連接,這樣實現了Java可以動態進行擴展。我們甚至可以從網路或者其他的地方載入一個二進位流作為程式的一部分。所以,我們通過編譯器將 ...
  • 將項目改成Module 打包混淆腳本 混淆配置proguard-rules.pro文件 開始打包 ...
  • 在做android圖片載入的時候,由於手機屏幕受限,很多大圖載入過來的時候,我們要求等比例縮放,比如按照固定的寬度,等比例縮放高度,使得圖片的尺寸比例得到相應的縮放,但圖片沒有變形。顯然按照android:scaleType不能實現,因為會有很多限制,所以必須要自己寫演算法。 通過Glide來縮放 其 ...
  • Glide是一個快速高效的多媒體管理和圖像載入的框架,封裝了Android平臺的多媒體的解碼,記憶體和硬碟緩存等,Glide支持解碼、顯示視頻、圖像和GIFs,Glide是基於定製的HttpUrlConnection,下麵是關於Glide的配置和使用。 Glide的配置 配置很簡單,只要在Module ...
  • Android常用許可權 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...