怎麼判斷對象"已死"?
1.引用計數法
不能解決對象循環依賴的問題。是以一般不用這種。
2.可達性分析算法。
GCRoots 不可達時 對象死,采用這個。
垃圾收集算法
1.标記清除算法
1.标記、清除階段效率不高。
2.标記清除之後會産生大量不連續的碎片,導緻配置設定較大的對象時候,無法找到足夠的連續記憶體。
2.複制算法
1.兩塊相同的記憶體空間,一塊使用,一塊空閑,導緻空間浪費。不存在碎片問題。
3.記整理算法
1.标記過程與"标記清除算法"一樣,整理過程是讓所有存活對象都往一端移動,然後直接清理掉邊界以外的記憶體。
4.分代收集算法。
把對象進行分代,新生代和來年代。
總結
新生代一般用複制算法,老年代一般用标記整理或者标記清除算法。
垃圾收集器
- Serial收集器
- 作用于新生代
- 單線程收集
- 采用複制算法
- 開啟方式:-XX:+UseSerialGC
- Client模式下的預設新生代收集器。進行垃圾收集時,必須Stop the world,直到它收集結束
- ParNew收集器
- 作用于新生代。
- 多線程收集
- -XX:+UseParNewGC-XX:ParallelGCThreans=2(2指定垃圾收集的線程數)
- Server模式下的預設新生代收集器
- ParallelScavenge收集器
- 新生代
- 多線程
- 複制算法
- -XX:MaxGCPauseMillis控制最大垃圾收集時間 -XX:GCTimeRatio 控制吞吐量大小
- 吞吐量優先收集器目标:控制吞吐量吞吐量=運作使用者代碼時間/(運作使用者代碼時間+垃圾收集時間)吞吐量越高說明CPU時間使用率越高。
- SerialOld收集器
- 老年代
- 單線程
- 标記整理算法
- 這個收集器的主要意義也是在于給Client模式下的虛拟機使用。如果在Server模式下,主要兩大用途:1.在JDK1.5以及之前的版本中與ParallelScavenge收集器搭配使用。2.作為CMS收集器的後備預案,在并發收集發生Concurrent Mode Failure時使用
- ParallelOld收集器
- 标記整理
- ParallelOld是ParallelScavenge收集器的老年代版本。這個收集器在1.6中才開始提供。在JDK1.5以及之前的版本中,Parallel Scavenge+Serial Old(單線程),無法充分利用多CPU的處理能力。1.6之後,終于有了名副其實的"吞吐量優先"收集器組合:Parallel Scavenge + Parallel Old。
- CMS
- 标記清除算法
- -XX:+UseConcMarkSweepGC新生代使用了PartNew
CMS在老年代的整個過程分為4個步驟:
1.初始标記stop the word 僅僅标記GC Roots能直接關聯到的對象,速度很快
2.并發标記進行GCRoots Tracing的過程(判斷對象是否仍在使用中)和使用者線程一起工作。3.重新标記stop the word 修正并發标記階段因使用者程式繼續運作而導緻标記發生變動的那一部分标記記錄。此階段比初始标記階段稍長,但遠比并發标記階段的時間短。
4.并發清除 和使用者線程一起工作。
G1 收集器
記憶體組成:Eden、 Survivor、 Old、 Humongous
記憶體變化:字元串内部池,已經在JDK7中從永久代中移除,JDK1.7中,存儲在永久代的部分資料就已經轉移到了JavaHeap或者是NativeHeap。但永久代仍存在于JDK1.7中,并沒完全移除,譬如符号引用(Symbols)轉移到了native heap;字面量(internedstrings)轉移到了javaheap;類的靜态變量(classstatics)轉移到了java heap持久代也移動到了普通的堆記憶體空間中,改為元空間 。
大對象的配置設定
1 TLAB(Thread Local Allocation Buffer)線程本地配置設定緩沖區
2 Eden區中配置設定
3 Humongous區配置設定