1. 程式人生 > >JVM記憶體區域劃分詳解

JVM記憶體區域劃分詳解

拿午休時間來發了這篇部落格,希望對大家有幫助
本文吸取《深入理解java虛擬機器》與多篇部落格精華詳細解說了JVM中記憶體劃分的情況。

大多數 JVM 將記憶體區域劃分:

  1. Method Area(Non-Heap)(方法區) ——執行緒共享

  2. Heap(堆) ——執行緒共享

  3. Program Counter Register(程式計數器) ——非執行緒共享

  4. VM Stack(虛擬機器棧,也有翻譯成JAVA 方法棧的)——非執行緒共享

  5. Native Method Stack ( 本地方法棧 )——非執行緒共享

JVM執行的時候會分配好 Method Area(方法區) 和Heap(堆)

而JVM 每遇到一個執行緒,就為其分配一個 Program Counter Register(程式計數器) , VM Stack(虛擬機器棧)和Native Method Stack (本地方法棧), 當執行緒終止時,三者(虛擬機器棧,本地方法棧和程式計數器)所佔用的記憶體空間也會被釋放掉。
非執行緒共享的那三個區域的生命週期與所屬執行緒相同,而執行緒共享的區域與JAVA程式執行生命週期相同,
所以gc只發生線上程共享的區域(大部分發生在Heap上)的原因。
這裡寫圖片描述

執行緒共享
一、方法區

  1. 有時候也稱為永久代(Permanent Generation),在該區內很少發生垃圾回收,在這裡進行的GC主要是方法區裡的常量池和型別的解除安裝
  2. 方法區主要用來儲存已被虛擬機器載入的類資訊、常量、靜態變數和即時編譯後的程式碼等資料。
  3. 方法區裡有一個執行時常量池用於存放靜態編譯產生的字面量和符號引用。執行時生成的常量也會存在這個常量池中。比如String類的intern()方法

擴充套件:

  • -XX:MaxPermSize設定上限
  • -XX:PermSize設定最小值 例:VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M

二、堆
在虛擬機器啟動時建立,幾乎所有的物件例項都在這裡建立,因此該區域經常發生垃圾回收操作
堆空間分為老年代和年輕代。剛建立的物件存放在年輕代,而老年代中存放生命週期長久的例項物件。年輕代中又被分為Eden區(聖經中的伊甸園)、和兩個Survivor區(From Space和To Space)。新的物件分配是首先放在Eden區,Survivor區作為Eden區和Old區的緩衝,在Survivor區的物件經歷若干次收集仍然存活的,就會被轉移到老年代


這裡寫圖片描述
堆中垃圾回收的時候注意一個大物件回收過程,描述如下:
年輕代與老年代控制元件分配如下:

  • Eden:80M

  • S1:10M

  • S2:10M

  • 老年代:100M

過程:

  1. 新建60M的物件O1,此時Eden有足夠記憶體吃下,所以60M被分配到Eden區
  2. 再新建40M物件O2,此時因為S1和S2的控制元件不足以容納下O1,所以O1被直接分配到老年代,而O2進入Eden區
  3. 清空O1、O2,新建90M物件O3,發現Eden不足以放下O3,O3被直接放入老年代中
  4. 清空O3,新建110M物件O4,O4發現Eden和老年代都沒有足夠控制元件,直接返回OutOfMemoryError

結論:

  • 當一個物件大於eden區而小於old區(老年代)時的時候會直接扔到old區
    而但物件大於old區時,會直接丟擲OutOfMemoryError(OOM)

    擴充套件:
    引數-XX:PretenureSizeThreshold:這個引數的單位是Byte,
    其作用是當新物件申請的記憶體空間大於這個引數值的時候,直接扔到old區
    -Xms:設定最小值
    -Xmx:設定最大值 例:VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
    若-Xms=-Xmx,則可避免堆自動擴充套件
    -XX:+HeapDumpOnOutOfMemoryError
    JVM會在遇到OutOfMemoryError時拍攝一個“堆轉儲快照”,並將其儲存在一個檔案中

執行緒私有
一、虛擬機器棧:

  1. 虛擬機器棧也就是我們平常所稱的棧記憶體,它為java方法服務,每個方法在執行的時候都會建立一個棧幀,用於儲存區域性變量表、運算元棧、動態連結和方法出口等資訊。
  2. 區域性變量表裡儲存的是基本資料型別和物件引用。區域性變數所需的記憶體空間在編譯器間確定
  3. 每個棧幀都包含一個指向執行時常量池中該棧幀所屬方法的引用,持有這個引用是為了支援方法呼叫過程中的動態連線.動態連結就是將常量池中的符號引用在執行期轉化為直接引用。

-Xoss引數設定本地方法棧大小(對於HotSpot無效)
-Xss引數設定棧容量 例: -Xss128k

二、本地方法棧
本地方法棧和虛擬機器棧類似,只不過本地方法棧為Native方法服務。

三、程式計數器
代表著當前執行緒所執行位元組碼的行號指示器
分支、迴圈、跳轉、異常處理和執行緒恢復等功能都需要依賴這個計數器完成
程式計數器是唯一一個java虛擬機器規範沒有規定任何OOM(Out Of Memory)情況的區域。

相關推薦

JVM記憶體區域劃分

拿午休時間來發了這篇部落格,希望對大家有幫助 本文吸取《深入理解java虛擬機器》與多篇部落格精華詳細解說了JVM中記憶體劃分的情況。 大多數 JVM 將記憶體區域劃分: Method Area

Java虛擬機器(JVM)執行時記憶體區域劃分

Java虛擬機器(JVM)記憶體區域劃分詳解 最近一直沒有怎麼更新自己的部落格,主要是由於老哥公司最近的一個招標專案忙得焦頭爛額,心力憔悴(ಥ_ಥ),趁著專案的空檔期來重構一下以前的一篇關於jvm記憶體區域劃分的部落格,仔細閱讀了一下之前的部落格,大量的文字敘

1.JVM中的五大記憶體區域劃分及快速掃盲

> 本部落格參考《深入理解Java虛擬機器》這本書 視訊及電子書詳見:[https://shimo.im/docs/HP6qqHx38xCJwcv9/](https://shimo.im/docs/HP6qqHx38xCJwcv9/) ## 一、快速掃盲 #### 1. JVM是什麼   JVM是Ja

JVM記憶體區域劃分Eden Space,Survivor Space,Tenured Gen,Perm Gen

  jvm區域總體分兩類,heap區和非heap區。heap區又分:Eden Space(伊甸園)、Survivor Space(倖存者區)、Tenured Gen(老年代-養老區)。 非heap區又分:Code Cache(程式碼快取區)、Perm Gen(永久代)、Jvm Stack(java虛擬機器棧)

JVM記憶體區域劃分及垃圾回收

   第一部分、閒扯+概述         近來在研讀《深入理解java虛擬機器》一書,讀完之後做個小結,算是記錄一下自己的學習所得,在成長的路上,只能死磕。 要理解JVM,就要先從其記憶體區域劃分開始,知道其由幾部分構成,再瞭解各部分的功能,這

jvm記憶體區域劃分,heap,Eden Space,Survivor Space,Survivor Space,Code Cache,Perm Gen

 jvm區域總體分兩類,heap區和非heap區。heap區又分:Eden Space(伊甸園)、Survivor Space(倖存者區)、Tenured Gen(老年代-養老區)。 非heap區又分:Code Cache(程式碼快取區)、Perm Gen(永久代)、Jvm Stack(

JVM記憶體區域劃分(JDK6 7 8中的變化)

在Java7之前,HotSpot虛擬機器中將GC分代收集擴充套件到了方法區,使用永久代來實現了方法區。這個區域的記憶體回收目標主要是針對常量池的回收和對型別的解除安裝。但是在之後的HotSpot

JVM記憶體區域劃分Eden Space、Survivor Space、Tenured Gen,Perm Gen解釋

jvm區域總體分兩類,heap區和非heap區。heap區又分:Eden Space(伊甸園)、Survivor Space(倖存者區)、Tenured Gen(老年代-養老區)。 非heap區又分:Code Cache(程式碼快取區)、Perm Gen(永久代)、Jvm

JVM記憶體區域劃分和簡介

JVM在執行java程式時會用一段空間來儲存程式執行期間需要用到的資料和相關資訊,這段空間一般被稱作為Runtime Data Area(執行時資料區),也就是我們常說的JVM記憶體。因此,在Java中我們常常說到的記憶體管理就是針對這段空間進行管理(如何分配和回收記憶體空間

JVM記憶體區域劃分和執行時的使用情況

1. JVM對自己的記憶體進行了劃分,分成了五個區域 a.暫存器:記憶體和CPU之間(系統相關) b.本地方法棧:JVM呼叫了系統中的功能(系統相關) c.方法和資料共享區:執行時期.class檔案進入的地方 d. 方法棧:所有方法執行的時候,進入記憶體中的位置 e

JVM記憶體區域劃分及其作用

和堆一樣,是各個執行緒共享的記憶體區域,用於儲存已被虛擬機器載入的類資訊、常量、靜態變數、和編譯器編譯後的程式碼(也就是儲存位元組碼檔案。.class)等資料,這裡可以看到常量也會在方法區中,是因為方法區中有一個執行時常量池,為什麼叫執行時常量池,因為在編譯後期生成的是各種字面量(字面量的意思就是值,比如in

JVM記憶體區域劃分以及垃圾回收機制

在我們寫Java程式碼時,大部分情況下是不用關心你New的物件是否被釋放掉,或者什麼時候被釋放掉。因為JVM中有垃圾自動回收機制。在之前的部落格中我們聊過Objective-C中的MRC(手動引用計數)以及ARC(自動引用計數)的記憶體管理方式,下方會對其進行回顧。而目前的JVM的記憶體回收機制則不是使用的引

JVM記憶體區域

JVM記憶體模型總體架構圖 程式計數器 多執行緒時,當執行緒數超過CPU數量或CPU核心數量,執行緒之間就要根據時間片輪詢搶奪CPU時間資源。因此每個執行緒有要有一個獨立的程式計數器,記錄下一條要執行的指令。執行緒私有的記憶體區域。如果執行的是JAVA方法,計數器

JVM記憶體區域(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen)

JVM區域總體分兩類,heap區和非heap區。 heap區又分為: Eden Space(伊甸園)、 Survivor Space(倖存者區)、 Old Gen(老年代)。 非heap區又分: Code Cache(程式碼快取區); Perm Gen(永

JVM——記憶體區域:執行時資料區域

關注微信公眾號:CodingTechWork,一起學習進步。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200707122307227.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow

JVM記憶體區域劃分 -- 學習

詳細檢視(轉自):https://www.cnblogs.com/dolphin0520/p/3613043.html 1.java程式具體執行過程   原始檔(.java)[-------java編譯器(java compiler)]>>>>位元組碼檔案(

第1篇--JVM記憶體區域劃分

學過C語言的朋友都知道C編譯器在劃分記憶體區域的時候經常將管理的區域劃分為資料段和程式碼段,資料段包括堆、棧以及靜態資料區。那麼在Java語言當中,記憶體又是如何劃分的呢?   由於Java程式是交由JVM執行的,所以我們在談Java記憶體區域劃分的時候事實上是指JVM記憶體區域劃分。在討論JVM記憶體區域

JVM記憶體區域劃分 -- 學習

1.java程式具體執行過程   原始檔(.java)[-------java編譯器(java compiler)]>>>>位元組碼檔案(.class)>>>>>>類載入器(classLoader)   [-

JVM執行時記憶體區域劃分

JVM執行時的記憶體區域分為:程式計數器,虛擬機器棧,本地方法棧,堆,方法區,執行時常量池以及直接記憶體區域 線面主要來分別說下這些區域的儲存內容作用 1.程式計數器    程式計數器是執行緒私有的,當前執行緒所執行的位元組碼行號指示器。位元組碼解析器通過改變這個計數器

JVM記憶體區域劃分(面試問題:你瞭解java記憶體模型麼)

 JVM的記憶體區域劃分   學過C語言的朋友都知道C編譯器在劃分記憶體區域的時候經常將管理的區域劃分為資料段和程式碼段,資料段包括堆、棧以及靜態資料區。那麼在Java語言當中,記憶體又是如何劃分的呢?   由於Java程式是交由JVM執行的,所以我們在談Java記憶