1. 程式人生 > >java虛擬機器記憶體分配原理概述

java虛擬機器記憶體分配原理概述

本文主要介紹在應用發起記憶體申請,到作業系統最終分配記憶體,採用了那些途徑和方法,並比較各種方法的優劣以及使用過程中應該注意那些點。
注意本文都是概述,如想詳細瞭解,需單獨詳細瞭解每一部分內容
1、應用在那些情況下發起記憶體申請
2、記憶體發起申請的步驟(3)
3、記憶體申請過程中對jvm記憶體模型的使用
4、申請記憶體用到哪些演算法
5、堆和堆記憶體分配

1、應用發起請求,要求系統分配記憶體

(這裡不考慮堆外記憶體,後續單獨解釋堆外記憶體)
1)、init階段,final和static修飾的類和方法
2)、應用中new()方法
3)、建立類時建立父類的物件申請記憶體
4)、java動態建立物件時反射技術(javaassist、asm等)

2、應用發起申請一般分為3部:

1)、建立物件例項
2)、為此物件分配記憶體
3)、指標指向記憶體地址
一般我們在做單例模式或者防止出現假物件的時候,我們會用volatile來防止指令重排(關於volatile後續會專門介紹),其實表面上看就是三步變一步。

3、記憶體申請一定會涉及到對記憶體模型各部分的操作

不同的場景,對記憶體的分配一定是有所區別的。
1)、物件在建立階段,在resolve階段,會對靜態化屬性值進行記憶體分配,並初始化值=0(此時test=0),如果是有final static修飾的則將初始化值為定義值(此時test=10)
private final static int test = 10;
這樣靜態修飾的屬性值分配在方法區。
2)、一個方法的開始,首先是方法的引數屬性、返回值等入棧,在棧區分配空間,同時如果有物件的new則需要去堆中建立物件例項。
3)、在堆中建立物件例項時,一般是兩種方式,列表和指標碰撞。在指向堆中的例項時候,一般也是兩種方式,直接指向(如果方法變化會需要重新指定)和通過控制代碼池(會使用額外的空間儲存控制代碼)
4)程式計數器 可以看做一個數據結構,線上程切換時候記錄下當前的位元組行數和狀態,以便於切回後能快速定位執行

4、記憶體分配方法(也被稱為快分配-tlab,慢分配-cas)

1)、TLAB(執行緒區域性分配快取技術))
thread local area buffer,在併發的時候為了提高記憶體分配的效率,在建立執行緒的時候為每個執行緒分配了一段記憶體,此時執行緒申請的時候在自己內部解決就好,這樣就不用去考慮併發問題,同時分配記憶體的效率跟c語言差不多。當然如果物件過大,仍然有去堆裡分配,所以併發問題都存在。這也是為什麼eden generation的物件越小越好
2)、cas
cas進行記憶體分配時,分配記憶體函式會返回top_add()返回 _top的eden區域的起始地址compare_to,當然也返回end_add()返回eden區域的結束值。在進行cas比較適合,compare_to與預期值進行比較,如果相同,則其他執行緒沒有操作該比變數。將_newtop賦值給_top,將其變成真正的eden的啟示值。這種方式也就叫指標碰撞

在進行記憶體分配的過程中,堆是最大的,也是java開發中用的最多的,所以著重分析一下堆。

5、堆和堆記憶體分配

此處分三部分解釋:堆的建立 、堆記憶體的分配 和 垃圾回收
堆 是jvm虛擬機器單獨開闢出來的一塊空間,由虛擬機器自己管理,用來滿足物件例項的分配的空間需求。
堆為什麼分代? 在建立的物件中,由的物件很大,由的物件生命週期很長,而大多數物件的都會很快被回收。如果都在eden區域,eden區域採用的複製演算法,對大和生命週期長的物件,是十分浪費cpu等資源的。因此將物件分代,不同代採用不同的演算法回收。
1)、堆的初始化
堆是universe根據initial_heap來完成java堆初始化,具體要根據虛擬機器配置。當然會根據回收演算法,配置回收策略。
eg:若虛擬機器配置UseParallelGC,則Java堆的堆型別為ParallelScavengeHeap(並行收集堆)
預設虛擬機器將使用GenCollectedHeap(分代收集堆)
其具體演算法、堆型別和回收策略如下:
這裡寫圖片描述

需要注意的一點就是,堆空間初始化完成以後,如果是64位環境會進行指標壓縮和TLAB等相關內容。通常64位JVM消耗的記憶體會比32位的大1.5倍,這是因為在64位環境下,物件將使用64位指標,這就增加了一倍的指標佔用記憶體開銷。
2)、堆記憶體分配
堆在初始化完成以後,我們以GenCollectedHeap 分代堆為例來解釋,一般GenCollectedHeap支援10個分代(一般只使用新生代和老年代)
那麼GenCollectedHeap是如何向系統申請記憶體空間的呢?
答案就在allocate()函式中 ,在申請之前,當然要對記憶體空間的大小和分塊數進行計算
預設的新生代和老年代的分塊數為1,而永久代的分塊數為2
後邊涉及到的內容很多,需要篇幅較長,後續再解釋。下面copy一張圖過來,有興趣的朋友可以看下
這裡寫圖片描述

3)、堆回收有更多gc的內容,會單獨介紹

相關推薦

java虛擬機器記憶體分配原理概述

本文主要介紹在應用發起記憶體申請,到作業系統最終分配記憶體,採用了那些途徑和方法,並比較各種方法的優劣以及使用過程中應該注意那些點。 注意本文都是概述,如想詳細瞭解,需單獨詳細瞭解每一部分內容 1、應用在那些情況下發起記憶體申請 2、記憶體發起申請的步驟(

Java JVM】Java虛擬機器記憶體分配幾個原則

1、大多數情況下,物件在新生代Eden區中分配。當Eden區沒有足夠空間進行分配時,虛擬機器將發起一次Minor GC 2、大物件直接進入老年代。大物件指需要大量連續記憶體空間的Java物件,最典型的

java虛擬機器-記憶體分配與回收策略

1.物件優先在Eden分配 大多數情況下,物件在新生代Eden區分配。當Eden區沒有足夠空間進行分配時,虛擬機器將發起一次Minor GC。 虛擬機器提供了-XX:+PrintGCDetails這個收集器日誌引數,告訴虛擬機器在傳送垃圾收集行為時列印記憶體回收日誌,並且在

Java虛擬機器記憶體分配機制與啟動引數說明

-Xms :表示java虛擬機器堆區記憶體初始記憶體分配的大小,通常為作業系統可用記憶體的1/64大小即可,但仍需按照實際情況進行分配。-Xmx: 表示java虛擬機器堆區記憶體可被分配的最大上限,通常為作業系統可用記憶體的1/4大小。但是開發過程中,通常會將 -Xms 與 -Xmx兩個引數的配置相同的值,其

深入理解Java虛擬機器--記憶體分配規則

新生代GC(Minor GC):指發生在新生代的垃圾回收動作,因此區域物件大多朝生夕死,所以Minor GC非常頻繁,一般回収速度也比較快 老年代GC(Major GC/Full GC):指發生在老年

java虛擬機器記憶體分配之新生代與老年代GC

1. Java堆中各代分佈: 圖1:Java堆中各代分佈 Young:主要是用來存放新生的物件。 Old:主要存放應用程式中生命週期長的記憶體物件。 Permanent:是指記憶體的永久儲存區域,主要存放Class和Meta的資訊,Class在被 Load的時候被放入PermGen space區域. 它和

Java虛擬機器記憶體管理(二)--垃圾收集器及記憶體分配策略

概述     Java記憶體執行時區域的各個部分,其中程式計數器、虛擬機器棧、本地方法棧3個區域隨執行緒而生,隨執行緒而滅;棧中的棧幀隨著方法的進入和退出而有條不紊地執行著出棧和入棧操作。每一個棧幀中分配多少記憶體基本上是在類結構確定下來時就已知的(儘管在執行期會由JIT編

《深入理解Java虛擬機器》個人讀書總結——JAVA虛擬機器記憶體

《深入理解Java虛擬機器》個人讀書總結——JAVA虛擬機器記憶體 最近在讀《深入理解Java虛擬機器》,網上對Java虛擬機器的總結有很多,自己覺得自己也應該記錄一點個人的讀書總結,以便日後複習方便。 隨著開發工作的逐漸深入,對Java的理解不能止步於crud,Java不像C語言

java虛擬機器(第二版) 第二章總結 (三)-手工復現java虛擬機器記憶體溢位(OutOfMemoryError異常)

  文章概述 的java虛擬機器記憶體溢位的簡要概述,復現堆記憶體,棧記憶體,方法區的執行時常量池記憶體等區域的溢位情況,以及上述區域發生記憶體溢位的判斷方式和解決思路。   1,概述:      IDE為eclipse,需要在執

jvm學習筆記(1)——java虛擬機器記憶體區域

一、java記憶體區域:      1、程式計數器(執行緒私有):     記憶體中較小的記憶體空間,可以當做當前執行緒所執行位元組碼的行號指示器。如分支、迴圈、跳轉、異常處理、執行緒恢復都需要依賴這個計數器完成。 2、java虛擬機

Java虛擬機器 記憶體管理與垃圾回收

java和C++之間有一堵由記憶體自動分配與垃圾回收所圍成的高牆,外面的人想進來,裡面的人想出去 主要內容 記憶體分佈 垃圾回收機制 垃圾收集器 Java記憶體分佈 當java虛擬機器執行程式時,會把由虛擬機器管理的記憶體劃分為不同的區域,他們的作用不同,建立和銷燬時間也不同,有的是虛擬

Java虛擬機器記憶體模型與執行緒

Java虛擬機器—記憶體模型與執行緒 Lyon Keep balance,Be a better man! ​關注他 3 人讚了該文章 前言: 本文主要介紹Java的記憶體模型和Java執行緒。 Java記憶體模型的主要目標是定義程式中各個變數的訪問規則,即在JVM

JVM系列第6講:Java 虛擬機器記憶體結構

看到這裡,我相信大家對於一個 Java 原始檔是如何變成位元組碼檔案,以及位元組碼檔案的含義已經非常清楚了。那麼接下來就是讓 Java 虛擬機器執行位元組碼檔案,從而得出我們最終想要的結果了。在這個過程中,Java 虛擬機器會載入位元組碼檔案,將其存入 Java 虛擬機器的記憶體空間中,之後進行一系列的初始化

JVM調優--------理解java虛擬機器記憶體模型

java虛擬機器記憶體模型是java程式執行的基礎,為了能使Java應用程式正常執行,JVM虛擬機器將記憶體資料分為程式計數器,虛擬機器棧,本地方法棧,Java堆和方法區 程式計數器用於存放下一條執行的指令;虛擬機器棧和本地方法棧用於存放函式呼叫堆疊資訊;java堆用於存放Java程式執行時所需

Confluence 提高Java虛擬機器記憶體

Confluence 提高Java虛擬機器記憶體 版本 系統:CentOS release 6.8 (Final)Java版本:1.8.0_162Confluence版本:6.8.5 問題描述 confluence記憶體使用率的配置都是預設的,相對會比較低,可以根據實際server的配置情況,升級記憶

JVM篇:淺談java虛擬機器記憶體模型

  博主最近嘗試著瞭解JVM,博主目前的一些理解,總之會隨著博主的深入瞭解慢慢完善吧 圖片來自網路 當JVM執行時,便會建立這五個區域,退出時銷燬。 JVM的五個區域:方法區、堆、棧(也可以稱為虛擬機器棧)、程式計數器、本地方法棧 博主在這裡說明一下:方法區概括了元空間

Java虛擬機器-記憶體管理

參考深入理解Java虛擬機器 執行時記憶體包括: 方法區(Method Area) 虛擬機器棧(VM Stack) 本地方法棧(Native Method Stack) 堆(Heap) 程式計數器(Program counter Register) 程式計數器

JAVA虛擬機器記憶體劃分學習

JAVA虛擬機器所管理的記憶體將分為以下幾個區:  1.程式計數器:主要包括程式的分支、迴圈、跳轉、異常處理等基礎功能;  2.棧:主要用於儲存區域性變數、方法出口、物件引用等資訊; 是執行緒私有的,生命週期與執行緒相同;  3.堆:主要儲存物件的例項;是執

java 虛擬機器記憶體劃分,類載入過程以及物件的初始化

涉及關鍵詞: 虛擬機器執行時記憶體 java記憶體劃分 類載入順序  類載入時機  類載入步驟  物件初始化順序  構造程式碼塊順序 構造方法 順序 記憶體區域   java記憶體圖  堆 方法區 虛擬機器棧 本地方法棧 程式計數器  區域性變量表   棧幀  java堆 執行時常量池   直接記憶體

JAVA虛擬機器JVM工作原理

JAVA虛擬機器JVM工作原理    https://blog.csdn.net/leftfist/article/details/85131366 提起JAVA,都知道它有個虛擬機器,因此可以跨平臺,一次編寫,到處執行。但具體原理是咋樣的?身為JAVA小白,豈可不知