我們學習的jvm都是sun公司出的基於hotspot的jvm。
jvm堆的結構
- 新生代:eden區,倖存0區,倖存1區
- 老年代
- 元空間(堆外內存,方法區)
因爲大部分java中的對象都是朝生夕死,所以搞了這一套gc(garbage collection)體系。
new出來的對象先放到eden區
當eden區滿了之後,進行一次minor gc,把eden區存活的對象移到倖存的to區,把倖存的from區的存活對象也移到to區(達到規定次數默認15次後移入老年區)。
當新生區全滿了之後,觸發一次major gc,等於全gc了一次
全放滿了就OOM(outofmemory)
默認情況下,分配的總內存是電腦內存的1/4,初始化的內存1/64
Jprofile和加參數看信息---這些先佔個坑
stackoverflow是棧滿了,OOM是堆中佔滿無法創造新對象了
以下代碼可以測試OOM錯誤
public class OOMTest { public static void main(String[] args) { List<Object> lists = new ArrayList<Object>(); for(int i=0;i<100000000;i++){ lists.add(new byte[1024*1024]); } } }
在IDEA中配置命令參數 -XX:+PrintGCDetails,可以輸出詳細的GC信息
可以看到信息非常豐富, 每一次GC都寫出來了
配置如上圖,可以充分配置內存。
使用Jprofiler可以對對象什麼的進行更加細緻的分析,需要生成dump文件(內存快照)
-XX:+HeapDumpOnOutOfMemoryError
GC
引用計數法:懂的都懂
複製算法:看圖,不會有碎片,但是浪費了一半的倖存區空間。適合於存活度低的情況。
標記清除算法和標記壓縮算法
標記清除算法,兩個階段,標記和清除
第一階段:標記。從根結點出發遍歷對象,對訪問過的對象打上標記,表示該對象可達。
第二階段:清除。對那些沒有標記的對象進行回收,這樣使得不能利用的空間能夠重新被利用。
一堆碎片
這兩種算法綜合一下,稱爲分代收集算法