Java虛擬機以內存

本文內容來自《深刻理解Java虛擬機》,主要是自身學習,用於記錄重點,方便回憶,複習。對應《深刻理解Java虛擬機》第二章。併發

Java虛擬機中內存區域

程序計數器(線程私有):可認爲是線程執行字節碼的行號指示器,經過該計數器的值,可知道線程下一條須要執行的字節碼。循環、異常處理、線程恢復都須要依賴該計數器來完成。沒個線程都一個獨立程序計數器,各線程計數器互不影響獨立存儲,爲「線程私有」。app

Java虛擬機棧(線程私有):通程序計數器,爲「線程私有」,生命週期與線程相同。每一個方法執行都會建立棧幀,用於存儲局部變量表、操做數棧等信息。局部變量表存放編譯期可知的基本數據類型,對象引用。可能會出現兩種異常:StackOverflowError:線程請求的棧深度大於虛擬機所容許的深度(如遞歸深度過深),OutOfMemoryError(擴展時沒法申請到足夠內存)。函數

本地方法棧(線程私有):與虛擬機棧做用相似,區別在於該區域是用於native本地方法。佈局

Java堆(線程共享):虛擬機啓動時建立,用於存放對象實例,垃圾收集器管理的主要區域,也稱爲「GC堆」,可處於物理上不連續的內存空間中,邏輯上是連續的便可。沒法擴展內存時,會拋出OutOfMemoryError。學習

方法區(線程共享):用於存儲被虛擬機加載的類信息,常量、靜態變量。可能拋出OutOfMemoryError。ui

常量池:方法區的一部分,用於存放編譯時生成的字面量、符號引用。可能會拋出OutOfMemoryError。編碼

直接內存:NIO中引入,經過native函數庫分配堆外內存,經過存儲在堆中的DirectByteBuffer對象對這塊內存進行操做。不受Java堆大小限制,編碼Java堆與Native中來回複製數據。spa

對象的建立

1、內存分配方法

一、假設Java堆中內存是絕對規整,用過的內存放一邊,空閒的內存放另外一邊,中間放一個指針做爲分界線的指示器,爲對象分配內存就僅僅是把指針向空閒空間那邊挪動一段與內存大小相等的距離,這種分配方法稱爲「指針碰撞」線程

二、若是內存不規整,虛擬機即需維護一個列表,記錄哪塊內存可用,分配時從列表中找出一塊足夠大內存劃分給對象,並更新列表,稱爲「空閒列表」。指針

2、併發處理方案

A線程讀取指針分配內存還未結束,B線程讀取舊指針分配內存,即會出現問題。

一、對內存空間分配動做進行同步處理,虛擬機上採用CAS,失敗重試保證更新原子性。

二、把內存分配的動做按照線程劃分在不一樣的空間進行。即每一個線程在Java堆中預先分配一小塊內存,稱爲本地線程分配緩衝。使用該方式,可經過-XX:+/-UseTLAB設定。

3、對象內存佈局

分爲3塊區域:對象頭+實例數據+對齊填充

對象頭分類兩部分:一、對象運行時數據:哈希碼、GC分代年齡、鎖狀態標誌等。32位虛擬機下爲32bit,64位虛擬機下爲64bit。二、類型指針,指向它的類元數據的指針,經過該指針肯定對象是哪一個類的實例。

實例數據:從父類中繼承的字段、類中定義的字段

對齊填充:對象其實地址必須是8字節的整數倍,若是對象頭是8字節的1或2倍數,若是實例數據不是8字節的整數倍,繼續填充。

訪問對象:

一、經過引用訪問對象 A a = new A(); a.getB():變量 --->引用池(句柄池,Java堆中)--->   對象

二、直接指針   new A().getB():                         ----->  對象

參數:

-Xms20m    設置堆初始化內存20m。

-Xmx20m   設置堆最大內存20m。

-Xss            設置棧的大小。

-XX:MaxDireMemorySize   指定最大直接內存。

-XX:+HeapDumpOnOutMemoryError  讓虛擬機出現內存益處時Dump出當前內存堆轉存快照,便於過後分析。

相關文章
相關標籤/搜索