JVM記憶體管理之JAVA語言的記憶體管理概述

来源:http://www.cnblogs.com/JavaBlackHole/archive/2017/08/17/7383821.html
-Advertisement-
Play Games

引言 記憶體管理一直是JAVA語言自豪與驕傲的資本,它讓JAVA程式員基本上可以徹底忽略與記憶體管理相關的細節,只專註於業務邏輯。不過世界上不存在十全十美的好事,在帶來了便利的同時,也因此引入了很多令人抓狂的記憶體溢出和泄露的問題。 可怕的事情還不只如此,有些使用其它語言開發的程式員,給JAVA程式員扣上 ...


引言     

 

     記憶體管理一直是JAVA語言自豪與驕傲的資本,它讓JAVA程式員基本上可以徹底忽略與記憶體管理相關的細節,只專註於業務邏輯。不過世界上不存在十全十美的好事,在帶來了便利的同時,也因此引入了很多令人抓狂的記憶體溢出和泄露的問題。

     可怕的事情還不只如此,有些使用其它語言開發的程式員,給JAVA程式員扣上了一個“不懂記憶體”的帽子,這著實有點讓人難以接受。畢竟JAVA當中沒有malloc和delete、沒有析構函數、沒有指針,剛開始接觸JAVA的程式員們又怎麼可能接觸記憶體這一部分呢,更何況有不少JAVA程式員還是跳了專業半路出家的朋友。

     不過事實儘管難以接受,但也確實有不少JAVA程式員對記憶體這部分可謂一竅不知,儘管掌握記憶體的相關知識,或許並不能給平時的開髮帶來翻天覆地的變化和好處,不過它仍然會潛移默化的提高你的技術水準,這一點在瞭解完記憶體管理之後,相信各位就會深有體會了。

      

記憶體劃分

 

     談到記憶體這一辭彙,它是在程式運行時才有的數據存儲區域,而對於這一塊區域的劃分,各個虛擬機有各自的劃分方式,不過它們都必須遵從JAVA虛擬機的基本規範去實現。

     虛擬機規範中,將記憶體劃分為六大部分,分別是PC寄存器、JAVA虛擬機棧、JAVA堆、方法區、運行時常量池以及本地方法棧

 

JAVA虛擬機規範與JAVA虛擬機

 

     這裡還需要解釋一下JAVA虛擬機規範和JAVA虛擬機的區別,顧名思義,JAVA虛擬機規範是一種對JAVA虛擬機實現的規範要求,是由oracle制定的,而我們平時常說的JAVA虛擬機一般是指的一種具體的JAVA虛擬機規範的實現。比如我們最經常使用的JAVA虛擬機hotspot,其實JAVA虛擬機還有很多種實現,甚至如果你對JAVA虛擬機規範有了深入的瞭解而且對此有興趣的話,可以寫一個自己的JAVA虛擬機,當然這其中的難度不難想象。

 

結構圖

 

     下圖是引用於百度文庫的一張JVM的結構圖,由於運行時常量池是由方法區分配出來的區域,所以此圖當中沒有運行時常量池。

 

 

記憶體區域詳解

 

     針對上面這張圖,記憶體就是指的矩形框當中運行期數據區這部分,下麵簡單介紹一下各個部分的作用:

     1、PC寄存器(線程獨有):全稱是程式計數寄存器,它記載著每一個線程當前運行的JAVA方法的地址,如果是當前執行的是本地方法,則程式計數器會是一個空地址。它的作用就是用來支持多線程,線程的阻塞、恢復、掛起等一系列操作,直觀的想象一下,要是沒有記住每個線程當前運行的位置,又如何恢復呢。依據這一點,每一個線程都有一個PC寄存器,也就是說PC寄存器是線程獨有的。

     2、JAVA虛擬機棧(線程獨有)JAVA虛擬機棧是在創建線程的同時創建的,用於存儲棧幀,JAVA虛擬機棧也是線程獨有的

    • 棧幀:簡單點說,可以解釋為是一個方法運行時,臨時數據的存儲區域,具體點說,它裡面包括了數據和部分的過程結果,與此同時,它又肩負著處理方法返回值、動態鏈接以及異常分派的任務。棧幀是隨著方法的創建而創建,隨著方法的結束而銷毀,如果方法拋出異常,也算方法結束。然而在每一個棧幀中,都有著自己的局部變數表以及操作數棧以及對當前類的運行時常量池的引用。
    • 局部變數表:它是一個方法局部變數的列表,是在編譯時期就寫入了class文件當中。簡單的理解,可以將它理解為一個對象數組,而裡面按照索引0到length-1分別對應於每一個局部變數,特別的,如果是實例方法的局部變數表,第0個局部變數會是一個指向當前實例的引用,也就是this關鍵字,其餘的局部變數則從索引1開始。
    • 操作數棧它是一個後進先出(LIFO)棧,而它的長度也是在編譯時期就寫入了class文件當中,是固定的。它的作用就是提供位元組碼指令操作變數計算的空間,比如簡單的,對於int a=9這句話來說,就需要先將9壓入操作數棧,再將9賦給a這個變數。

     3、JAVA堆(全局共用):這一部分是JAVA記憶體中最重要的一部分,之所以說是最重要的一部分,並不是因為它的重要性,而是指作為開發人員最應該關註的一部分。它隨著JAVA虛擬機的啟動創建,儲存著所有對象實例以及數組對象,而且內置了“自動記憶體管理系統”,也就是我們常說的垃圾搜集器(GC)。JAVA堆中的記憶體釋放是不受開發人員控制的,完全由JAVA虛擬機一手操辦。對於JAVA虛擬機如何實現垃圾搜集器,JAVA虛擬機規範沒有明確的規定,也正因如此,我們平時使用的JAVA虛擬機中提供了許多種垃圾搜集器,它們採用不同的演算法以及實現方式,已滿足多方面的性能需求。

     4、方法區(全局共用):方法區也是堆的一個組成部分,它主要存儲的是運行時常量池、欄位信息、方法信息、構造方法與普通函數的位元組碼內容以及一些特殊方法。它與JAVA堆的區別除了存儲的信息與JAVA堆不一樣之外,最大的區別就是這一部分JAVA虛擬機規範不強制要求實現自動記憶體管理系統(GC)。

     5、本地方法棧(線程獨有)本地方法棧是一個傳統的棧,它用來支持native方法的執行。如果JAVA虛擬機是使用的其它語言實現指令集解釋器的時候,也會用到本地方法棧。如果前面這兩種都未發生,也就是說如果JAVA虛擬機不依賴於本地方法棧,而且JAVA虛擬機也不支持native方法,則不需要本地方法棧。而如果需要的話,則本地方法棧也是隨每一個線程的啟動而創建的。

     上面五個記憶體區域,除了PC寄存器之外,其餘四個一般情況下,都要求JAVA虛擬機實現提供給客戶調節大小的參數,也就是我們常用的Xms、Xmx等等。

 

記憶體管理

 

     記憶體管理分為記憶體分配和記憶體釋放,看一下上面的五個記憶體區域,其實可以大致分為兩部分,一部分是全局共用,一部分是線程獨有

     對於線程獨有的這部分記憶體,都是隨著線程的啟動而創建,而當線程被銷毀時,記憶體也就隨之釋放。這一部分記憶體,不需要垃圾搜集器的管理,而是JAVA虛擬機來主動管理,每當一個線程被創建的時候,JAVA虛擬機就會為其分配相應的PC寄存器和JAVA虛擬機棧,如果需要的話,還會有本地方法棧。相應的,當一個線程被銷毀的時候,JAVA虛擬機也會將這個線程所占有的記憶體全部釋放

     相對於線程獨有的那部分記憶體,全局共用的這部分記憶體更加難以處理,不過這隻是針對於虛擬機的實現來說,因為這一部分記憶體是要實現自動記憶體管理系統(GC)的。

     全局共用的這部分記憶體(以下簡稱堆),記憶體分配主要是由程式員顯示的使用new關鍵字來觸發的,至於new出來的這部分記憶體在哪分配,如何分配,則是JAVA虛擬機來決定。而這部分記憶體的釋放,則是由自動記憶體管理系統(以下簡稱GC)來管理的

     通常情況下,堆記憶體分配是要依賴於GC的策略與實現的,在分配的時候,就要考慮好到時候如何回收這部分記憶體。也是正因為如此,對於記憶體分配這一部分的講解來說,我們必須得先瞭解記憶體是如何被回收的,才能更好的理解記憶體要怎麼被分配。

結束語

     

      本次對於JAVA語言中記憶體管理的概述就到此結束了,接下來的章節會著重講解一下GC的原理以及實現方式,請各位敬請期待吧。

 

轉載一位前輩博客,出處:http://www.cnblogs.com/zuoxiaolong

 


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

-Advertisement-
Play Games
更多相關文章
  • 想挖個坑督促自己練技術,有時候想到一個項目,大概想了一些要實現的功能,怎麼實現。現在覺得自己差不多能完成QQ空間的主要功能了。準備立個牌坊,寫一個類似功能的網站。並且把進度放到這裡來。 初步計劃實現以下功能 1、用戶註冊、登錄、信息修改; 2、用戶進行好友關註、推送好用動態; 3、發表日誌、評論和評 ...
  • 目錄 題目描述 思路 程式(C++版&java版) 詳解 題目描述: 思路: 這道題實在是太經典,一道題裡面考察了幾個知識點: 1.鏈表是否有環的判斷 2.鏈表若有環,要找到環的入口節點 3.兩個鏈表的多種情況分析 另外,左老師講得實在是太贊了. 程式(詳解在後面): 詳解 先把幾種情況羅列一下: ...
  • 附圖一張: 今天閑來無事做,就想起同程SRC有一個公開漏洞模塊。然而閑的蛋疼的我就有了對其寫一個爬蟲將漏洞列表爬下來的衝動。有兩個版本,一個是單線程的。另一個是多線程的版本。 單線程版本: 多線程版本: 多線程使用的是Threading+Queue #coding=utf-8 import requ ...
  • 二、初識C語言 編程語言有很多種,主要分為三大類,分別是機器語言、彙編語言、高級語言。電腦只能識別和理解二進位代碼,也就是0和1。想一下,用機器語言來開發,我們得記住多少用0和1兩個數字所組成的指令代碼以及其代碼涵義?顯然,這是不合理的,這樣的編程枯燥且繁瑣費力,也容易出錯。彙編語言應運而生,彙編 ...
  • os模塊調用操作系統介面的模塊 相關方法或屬性: getcwd() 獲取當前的操作目錄,等同於linux中的pwd命令。 調用:os.getcwd() chdir() 改變python腳本的工作目錄。 調用:os.chdir(path) (path以字元串形式傳入) 例如: curdir 當前目錄 ...
  • 1.Rock Paper Scissors(剪刀 石頭 布) 說明:在電腦科學中有一種特別重要的游戲,因為它本身很簡單,可以用來創建非常狡猾的人工智慧演算法來對抗人類(或彼此),預測對手的行為。 這個古老的游戲是在兩個參與者之間進行的,他們同時用他們的手勢——石頭,紙或者剪刀。如果兩人都投了相同的手 ...
  • 昨天有個大牛說我啰嗦,眼光比較細碎,看不到重點。太他爺爺的有道理了!要說看人品,還是女孩子強一些。原來記得看到一個男孩子的抱怨,說怎麼兩人剛剛開始在一起,女孩子在心裡就已經和他過完了一輩子。哥哥們,不想這麼遠行嗎?看看何潔,看看帶著倆娃跳樓的媽媽。所以現在的女孩子是很明白的,有些男孩子個子不高,其貌 ...
  • 關於Spring總結 Spring引入 傳統的基於mvc的項目框架結構:Entity / dao / service / action 簡單用戶訪問流程:/user.action Tomcat (伺服器創建Action、Service、dao 引出思考: 1. 對象創建創建能否寫死? 2. 對象創建 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...