線程隔離:VM Stacks(其中有Stack Frame, Stack Frame中有局部變量表,局部變量表中存有對象引用)、Native Method Stack、PC Counterhtml
線程共享:方法區(Method Area)(包括class代碼、字符串常量等)、堆(Heap)java
http://blog.jamesdbloom.com/JVMInternals.html算法
,其中能夠選擇各類回收算法:數組
說道垃圾收集,判斷對象是否存活,包括引用計數(因無法解決循環引用問題而被拋棄,但仍然在一些網頁應用語言中使用),一種是GC Roots(這包括VM Staks中的引用,類的靜態屬性引用的對象、方法區的常量引用、Native Method Stack中JNI方法引用的對象)引用鏈。 全局性引用、執行上下文。多線程
圖片請參考https://blogs.oracle.com/jonthecollector/entry/our_collectors併發
早期的有停頓,減小停頓,減小對用戶影響成爲目標。oracle
下列的收集器都使用了SafePoint,一種GC Roots方法中藉助OopMap完成收集GC Roots引用信息的快照時間點,有搶先式中斷(被動式的,指的是gc線程去控制)和主動式中斷(GC指定標誌位讓用戶線程去輪詢)。jvm
Serial收集器:有停頓,對於運行在Client模式下虛擬機是好的選擇。新生代採起復制算法(內存分配沒必要1:1,由於有老生代的擔保)、老生代採起mark-compact算法(讓全部存活對象都向一端移動,然後清除另外一端)ide
ParNew收集器:使用多線程收集,配置參數包括控制參數、收集算法、Stop the world、對象分配規則、回收策略;是Serial的多線程版本,默認開啓與CPU相同線程數(-XX:ParallelGCThreads)。是不少運行在Server模式下的虛擬機中的首選新生代收集器(由於能夠與CMS配合使用)。是使用了-XX:+UseConcMarkSweepGC選項後的默認新生代收集器,也能夠用-XX:+UseParNewGC選項指定。wordpress
Parallel Scavenge收集器:新生代收集器,目標是達到一個可控的吞吐量,高吞吐量達到的目標是儘快完成程序的運算任務,適合後臺運算需求型。用這兩個參數來精確控制,-XX:MaxGCPauseMillis, -XX:GCTimeRatio,GC停頓時間要小多是以犧牲吞吐量和新生代空間來換取的。還有-XX:UseAdaptiveSizePolicy用於自適應調整新生代大小、Eden與Survivor比例、晉升老生代年齡等細節參數(http://docs.oracle.com/javase/1.5.0/docs/guide/vm/gc-ergonomics.html)。不過沒法和CMS一塊兒工做。-XX:+UseParallelGC開啓的是PS+Serial Old(PS MarkSweep)組合。
Serial Old收集器:是Serial的老年代版本,使用Mark-Compact算法。主要也仍是client模式下使用,或者做爲cms的後備,或者在jdk1.5及之前與Parallel Scavenge一塊兒配合使用。
Parallel Old收集器:是Parallel Scavenge的老年代版本,使用多線程和Mark-Compact算法。從jdk1.6開始提供,在這以前新生代Parallel Scavenge只能尷尬的選用Serial Old做爲老年代配合)。要開啓的話得用UseParallelOldGC,在注重吞吐量和CPU敏感的情形下較適用。
CMS(Concurrent Mark Sweep)收集器:以得到最短響應時間爲目標的收集器,是基於mark-sweep算法。CMS initial mark(GC Roots直接的,須要stop the world,但時間很短),CMS concurrent mark(GC Roots引用鏈,與與用戶線程併發)、CMS remark(解決併發過程當中可能發生的變化,stop the world,時間也不會很長)、CMS concurrent sweep(併發)。優勢是低停頓,缺點是對cpu敏感、可能觸發Concurrent Mode Failure從而致使一次Full GC產生(這是老年代中,cms current sweep期間程序繼續運行會產生新的垃圾、產生的垃圾充滿了本來給這期間用戶線程運行所預留的空間,這樣內存不夠,會讓jvm臨時啓用serial old收集器來從新進行老年代的垃圾手機,停頓時間很長),還有即內存碎片(這經過在碎片太多快Full GC時開啓合併整理來改善,內存整理過程是沒法併發的,會增長停頓時間)。開啓時使用UseConcMarkSweepGC開啓的是ParNew+CMS+Serial Old組合。
G1(Garbage First)收集器:在jdk7u4中成爲正式。把java內存堆分爲多個region,避免進行全區域的垃圾收集而是維護一個優先列表。Initial Marking、Concurrent Marking、Final Marking、Live Data Counting and Evacuation(篩選回收)。最後篩選回收階段先對各region的回收價值和成本進行排序,然後根據用戶指望的GC停頓時間來指定回收計劃。
對於老年代區域對新生代區域的變量引用,使用card marking(卡片標記),只掃描老年代區域中「Dirty」的部分。
對象優先在新生代Eden區分配:內存不夠時會有Minor GC(很頻繁,速度很快)使用copying算法,copy到survivor區。
大對象直接進老年代:(很長的字符串和數組)
長期存活的對象將進入老年代:對象在Survivor中每熬過一次Minor GC就變「老」一點。
動態對象年齡判斷。
空間分配擔保:若是不夠時是會觸發Full GC。老年代的連續空間大於新生代對象總大小或者歷次晉升的平均大小就會Minor GC,不然Full GC
Young(Eden+2*Survior) /Tenured /Perm(method area)
http://www.cubrid.org/blog/dev-platform/understanding-java-garbage-collection/
在HotSpot VM中,爲了加快MemoryAllocation,使用了兩個技術:
bump-the-pointer:使用指針跟蹤最後一次內存分配的對象,這樣當新的內存分配請求到來時,檢查剩下是否夠便可。
TLABs(Thread-Local Allocation Buffers):this allows each thread to hava a small portion of its Eden space ths corresponds to its own share.
與程序編譯運行時的概念,main memory/ working memory的區別與聯繫:
兩個層面的,若要對應。main memory------堆中的對象實例數據部分;working memory------VM Stacks的部分區域
從硬件上,有可能main memory是對應物理內存,而working memory對應寄存器和cache中。
jmap:
https://thenonsensetechlogs.wordpress.com/2014/04/09/error-attaching-to-process-sun-jvm-hotspot-debugger-debuggerexception-cant-attach-to-the-process-solved/