Jdk:Java程式設計語言、Java虛擬機、Java API類庫。Jdk是用於支持Java程式開發的最小環境。Jre:Java API類庫中的Java SE API子集、Java虛擬機。Jre是支持Java程式運行的標準環境。Program Counter Register:較小的記憶體空間,可以看...
Jdk:Java程式設計語言、Java虛擬機、Java API類庫。
Jdk是用於支持Java程式開發的最小環境。
Jre:Java API類庫中的Java SE API子集、Java虛擬機。
Jre是支持Java程式運行的標準環境。
Program Counter Register:較小的記憶體空間,可以看作當前線程所執行的位元組碼的行號指示器。是唯一一個Java虛擬機規範中沒有規定OutOfMemoryError的區域。
VM Stack:生命周期和線程相同,它描述了Java方法執行的記憶體模型:每個方法在執行的同時都會創建一個棧幀用於存儲局部變數表、操作數棧、動態鏈接、方法出口等信息。
兩種異常:StackOverflowError、OutOfMemoryError
Native Method Stack:類似VM Stack,且Sun HotSpot直接合二為一!
Heap:最大的一塊記憶體,虛擬機啟動時創建,唯一目的就是存放對象實例的。
Method Area:存儲已被虛擬機載入的類信息、常量、靜態變數、即使編譯器編譯後的代碼等數據。Java虛擬機規範稱其為堆的邏輯部分,別名卻叫Non-Heap(非堆),或永久代。
Runtime Constant Pool:方法區的一部分
Direcrt Memory:不是虛擬機運行時數據區的一部分,也不是虛擬機規範定義的記憶體區域。
對象的創建—關鍵字new
記憶體劃分方法:指針碰撞(堆記憶體規整,通過移動指針分配記憶體)、空閑列表(堆記憶體不規整,通過更新記憶體列表分配記憶體)。
TLAB(Thread Local Allocation Buffer):本地線程分配緩衝,對於所創建的線程都會分配一塊獨立的空間,避免記憶體分配衝突,提升記憶體分配效率。
對象的記憶體佈局:對象頭(Header)、實例數據(Instance Data)和對其填充(Padding)。
對象的訪問定位:Java程式通過棧上的reference(引用)數據來操作堆上的具體對象。
方式:句柄和直接指針(Sun HotSpot)。
OutOfMemoryError異常實戰
工具:Eclipse Memory Analyzer
記憶體泄漏Memory Leak、記憶體溢出Memory Overflow
判斷對象是否死亡—堆記憶體
1、引用計數演算法:給對象添加一個引用計數器,每當有一個地方引用它是,計數器加1;當引用失效時,計數器減1;任何時刻計數器為0的對象就是不可能再被使用的。
2、可達性分析演算法:通過“GC Roots”對象作為起始點向下搜索,當一個對象到GC Roots沒有任何引用鏈相連,證明此對象是不可用的。
To be or not to be!
1、 使用上述演算法判斷對象是否使用;
2、 如果不再被使用,則標記並篩選;
刷選是否有必要執行finalize()方法,如下情況不需要執行:
l 對象沒覆蓋finalize()方法;
l finalize()方法已經被虛擬機調用過;
3、 如果有必要執行,則把該對象放置在F-Queue隊列中;
4、 由一個虛擬機自動建立、低優先順序的Finalizer線程去執行它,即由虛擬機來觸發執行;
5、 GC對隊列中的對象會進行第二次標記,即給對象重新建立引用,就能移除回收集合;
註意:任何一個對象的finalize()方法都只會被系統調用一次!
方法區回收
主要兩部分:廢棄常量和無用的類
控制參數
-Xnoclassgc:關閉虛擬機對class的垃圾回收功能;
-verbose:class:監視有多少類被載入;
-XX:TraceClassLoading、-XX:TraceClassUnLoading:列印類被載入和卸載的過程信息;
註意:在大量使用反射、動態代理、CGLib等ByteCode框架、動態生成JSP以及OSGI這類頻繁自定義ClassLoader的場景都需要虛擬機具備類卸載的功能,以保證永久代不會溢出!
垃圾收集演算法
1、標記—清除演算法:容易產生記憶體碎片
2、複製演算法:堆被劃分成兩個不同的區域:新生代(Young) 主要是用來存放新生的對象、老年代(Old) 主要存放應用程式中生命周期長的記憶體對象。新生代 (Young)又被劃分為三個區域:Eden、From Survivor、To Survivor。
預設的,新生代(Young)與老年代(Old)的比例的值為1:2
預設的,Edem : from : to = 8 : 1 : 1
3、標記—整理演算法
4、分代收集演算法
HotSpot演算法實現GC
枚舉根節點:逐個檢查;(Stop The World,GC執行時必須停頓所有Java執行線程)
在OopMap協助下,HotSpot可以快速並準確地完成枚舉。
安全點:只有在安全點才能停頓開始GC
安全區域:安全點的擴展,在安全區域可以停頓開始GC
垃圾收集器:記憶體回收的具體實現。
GC日誌
GC常用參數
記憶體分配策略
1、對象優先在Eden分配:新生代GC(Minor GC)、老年代GC(Major GC/Full GC)
2、大對象直接進入老年代:
3、長期存活的對象將進入老年代:給每個對象定義一個年齡(Age)計數器。對象在Eden出生並經過第一次Minor GC後仍然存活,並且能被Survicor容納的話,將被移動到Survivor空間,並對象年齡設為1。對象在Survivor中每“熬過”一次Minor GC,年齡就增加1,當年齡增加到一定程度(預設15),晉升到老年代中。
4、動態對象年齡判定:虛擬機並不是永遠要求對象年齡到一定程度才能晉升老年代,如果在Survivor空間中相同年齡所有對象大小總和大於Survivor空間的一半,年齡大於或等於該年齡的對象就可以直接進入老年代。
5、空間分配擔保:老年代的連續空間大於新生代對象總大小或者歷次晉升的平均大小就會進行Minor GC,否則將進行Full GC。
工具
JDK1.5中,getAllStackTraces()用於獲取虛擬機中所有線程的StackTraceElement對象。
HSDIS:JIT生成代碼反彙編。
JConsole:Java監視與管理控制平臺,基於JMX。
VisualVM:多合一故障處理工具