java是強類型高級語言
JVM(Java Virtual Machine,Java虛擬機)是Java平臺的核心組件,它是一個虛擬的計算機,能夠執行Java字節碼(bytecode)。
1、區域劃分
JVM對Java內存的管理也是分區分塊進行,方便管理。
這一部分稱之為
運行時數據區域
這個區域也可以進行細分
區域a:線程私有,對別的線程不可見
????????棧——存儲方法調用和局部變量
????????????????本地方法棧——用于本地方法的存儲,本質上和虛擬機棧沒有 區別(很多虛擬機都將二者一起管理)
????????本地方法(Native Method) 是指由非 Java 語言(如 C、C++ 等)實現,并通過 Java 虛擬機(JVM)調用的方法。它的作用是讓 Java 代碼能夠與底層系統或硬件交互,彌補 Java 語言在性能或系統級操作上的局限性。
????????????????虛擬機棧——存儲方法的局部變量,出口等一系列數據(棧幀)
程序計數器——指向線程正在執行的字節碼行號(唯一不會發生OOM(OutOfMemoryError)的區域)
區域b:線程共享
????????方法區——類信息,常量,靜態變量,JDK 8后由元空間(Metaspace)實現,使用本地內存
運行時常量池:方法區的一部分,存放編譯期生成的各種字面量和符號引用
????????堆(最大)——為對象和數組分配內存的地方,CG主要管理的區域
2、對象的組成
創建對象和銷毀對象的過程是什么
2.1 分配內存給對象的方式
都采用循環CAS策略進行并發情況下的差錯避免
假如內存是規整的:指針碰撞,移動指針分配空間即可,但當某塊內存被回收后需要對當前內存進行整理
假如內存是不規整的:建立空閑列表,需要挑選一個合適大小的空間分配,但會出現大量的空間碎片
TLAB:考慮到對象的創建是一個十分頻繁的內容,指針爭奪和CAS要大量進行,所以每個線程提前分配一塊內存,以減少爭奪指針的次數,這個叫本地線程分配緩存(Thread Local Allocation Buffer,TLAB),分配后初始化為零值。
2.2 對象的內存布局
對象頭
MarkWord標記字——存儲對象信息,是一個動態定義的數據結構。會有不同的標志位,不同標志位代表后續存儲的內容不同
指向對象類型的指針——表明對象類型
如果對象是數組時,會額外存儲數組長度
實例數據
private string name等的和對象相關信息,就是實例數據。可以存基本類型也可以存地址指針。
對齊填充
填充到要求大小
2.3對象的訪問方式
我們的Java程序會通過棧上的reference數據來操作堆上的具體對象。
使用句柄
reference中存儲的就是對象的句柄地址,句柄中包含了對象實例數據與類型數據各自具體的地址信息,棧——>句柄池——>實例池&方法區
直接指針
reference中存儲的直接就是對象地址,棧——>堆——>方法區
- 使用句柄來訪問的最大好處就是reference中存儲的是穩定句柄地址,對象位置發生移動時,只需要修改句柄地址,不需要修改reference
- 直接指針來訪問最大的好處就是速度更快,它節省了一次指針定位的時間開銷,但在大量訪問的情況下這個好處可以被忽略
3.垃圾收集
3.1 哪些是垃圾?
判斷生死
腦門刻字法(引用計數法):引用指向該對象——>計數+1
引用斷開指向該對象——>計數-1,為0就回收,但單純的引用計數就很難解決對象之間相互循環引用的問題。
平地長樹法(可達性分析):現行虛擬機使用的主要方式。從CGRoot開始向下搜索,不可達的對象被判定為可回收對象。
GC Roots的對象包括以下幾種:虛擬機棧中的對象、方法區靜態屬性引用的對象、方法區常量引用的對象、本地方法棧引用的對象、虛擬機內部對象、同步鎖持有的對象,還有一些會被臨時加入
引用類型
????????強引用:在代碼中普遍存在的引用賦值
????????軟引用:還有用但非必須可以作為緩存使用
????????弱引用:可以作為緩存,被下一次垃圾回收回收
????????虛引用
3.2 怎樣回收?
分代收集理論
JVM會把性質類似的對象放在一起集中管理
弱分代假說
????????不需要分代,因為大部分對象死的都很快
強分代假說
????????需要分代,獲得時間越長的對象越傾向于活下去
把Java堆劃分為不同的區域,回收對象根據年齡劃分:新生代、老年代。
新生代的回收頻率要高于老年代。
跨代引用假說
????????相對于同代引用僅占極少數。新生代引用老年代。老年代引用新生代。這種情況下會在被老年代引用的新生代上做標記(記憶集),標記出該新生代被哪個老年代的區域引用,此時把老年代的那一內存小塊放入CGRoot中進行掃描(CGRoot的特殊部分)
3.3 收集算法
標記-清除算法
????????算法簡單,但缺點明顯:空間碎片問題,stop the world問題這要求用戶線程完全停止。
空間碎片化的解決方式:
標記-復制算法
? ? ? ? ?劃分為AB區域,左右復制刪除清空,僅適用于收集效率高的場合(朝生夕死),并且只有一半的有效空間。(適用于新生代)
????????標記復制優化——劃分為三個區域:Eden區(8)Survivor區(From/To)(1)
標記-整理算法
????????把存活的部分集中在前部,清除后部分的。沒有空間碎片,但是需要移動對象
3.4 HotSpot算法實現細節
根節點枚舉
我們通過OopMap來實現根節點枚舉,讓虛擬機在掃描時就直接得到根節點的信息,它的核心作用是讓垃圾回收器快速準確地識別棧和寄存器中哪些位置包含指向對象的引用(即 "對象指針")。
遍歷oopmap即可搜集到根節點
安全點
OopMap 與安全點緊密相關,安全點是程序執行過程中可以暫停并執行 GC 的位置,每個安全點都關聯一個 OopMap。
安全點位置的選取基本上是以“是否具有讓程序長時間執行的特征”為標準進行選定的。(方法調用,循環跳轉,異常跳轉等指令序列復用)
如何在垃圾收集時,讓所有線程都跑到安全點?
搶占式中斷-先中斷所有線程,不能中斷時恢復。不好
主動式中斷-借助標志
安全區域
安全區域是指能夠確保在某一段代碼片段之中,引用關系不會發生變化,因此,在這個區域中任意地方開始垃圾收集都是安全的。
記憶集與卡表
記憶集:所有涉及部分區域收集行為的垃圾收集器中,用于記錄從非收集區域指向收集區域的指針集合的抽象數據結構
記憶集有三種精度:字長精度、對象精度、卡精度
卡精度——卡表實現,卡頁內存有跨代指針,標志位置1,此時該卡表”變臟“,只需遍歷變臟卡頁就可得到區域。
寫屏障
HotSpot通過寫屏障維護卡表狀態。這是對引用對象賦值的一個環形通知(細分為寫前、寫后屏障)
3.5并發的可達性分析
基于一個保持一次性快照——對象引用關系不可改變
三色標記:
????????黑:已經被垃圾收集器放問過,且所有引用已經被掃描
????????白:尚未被標記
????????灰:已經被垃圾收集器放問過,且有引用未被掃描
????????由于這個過程會和用戶進程并發進行,此時會有浮動垃圾的產生和引用被誤刪的情況:當同時滿足 1 賦值器插入了一條或多條從黑色對象到白色對象的新引用,2 賦值器刪除了全部從灰色對象到該白色對象的直接和間接引用
解決方案:
????????增量更新:破壞1
????????原始快照:破壞2
3.6常見的收集器
Serial收集器:
????????新生代標記-復制,老年代標記-整理
ParNew收集器:
????????是Serial收集器并發版本。新生代標記-復制,老年代標記-整理
Parallel Scavenge收集器:
????????標記-復制法目標是達到一個可控制的吞吐量
Serial Old收集器:
????????標記-整理法。它作為CMS發生失敗的后備預案,在并發收集發生Concurrent Mode Failure時使用
Parallel Old收集器:
????????標記-整理算法
CMS(Concurrent Mark Sweep)收集器
????????是一種以獲取最短回收停頓時間為目標的收集器。基于標記-清除算法實現,整個過程分為四個階段
????????初始標記(stop the world)標記直接關聯到的對象,速度很快
????????并發標記 遍歷整個路徑,但可以并發運行
????????重新標記(stop the world)
????????并發清除 也可以并發運行
其中耗時最長的并發標記和并發清除階段
有三個明顯的缺點:
- CMS對處理器資源非常敏感
- 由于CMS收集器無法處理“浮動垃圾”(產生于標記結束后的垃圾)
- CMS運行期間預留內存無法滿足新對象分配需要(啟動閾值為92%)
- 產生空間碎片
GI收集器(Garbage First)
????????是一種主要面向服務端應用的垃圾收集器。收集器面向局部收集的設計思路和基于Region的內存布局形式。
????????目標是:支持一個在長度為M毫秒的時間段內,花在垃圾收集上的時間不超過N毫秒。
基于Region幫助實現這個目標,把Java內存劃分為多個大小相等的區域,采用MixedGC模式,使回收收益最大
????????內存碎片問題不嚴重,但內存負載較高
3.7低延遲垃圾收集器
衡量垃圾收集器的三項最重要的指標是:
????????內存占用(Footprint)
????????吞吐量(Throughput)
????????延遲(Latency)
3.8內存分配與回收策略
- 對象優先在Eden區
- 大對象直接進老年代
- 長期存活對象將進入老年代:對象年齡計數器(對象頭)
- 動態年齡判定:動態調整進入老年代的年齡限制
- 空間分配擔保:判斷老年代空間是否滿足新生代晉升(與歷史平均值對比)