認識java虛擬機器(2)
物件的建立:需要類的載入。物件建立圖:
<init>方法是程式碼塊(構造方法)
new類名和呼叫物件方法是可見的,
物件的記憶體分配。
堆是不連續的儲存空間,堆記憶體是規整的,用過的放一邊,沒用過的放在一邊。分配記憶體是指標移動的過程。
1.指標碰撞的記憶體分配方式:(java堆規整)
2.空閒列表:(java堆不規整)
1是使用的在一邊,沒有使用的在另一邊,如果是使用的和沒有使用的交錯在一起的情況,它會建立一張空閒列表,空閒的記憶體區域都在這張表裡,java堆的規整與否是由回收策略決定的
它會造成執行緒不安全問題(多執行緒一起發起多個請求,向空閒列表裡申請記憶體,便會造成記憶體混亂問題)
1.執行緒同步(加鎖解鎖)
2.
物件的結構:
header(物件頭)
1.自身執行時資料【mark word】(雜湊值,GC分代年齡(為後面垃圾回收的各大演算法服務),鎖狀態標識,偏向時間戳,執行緒持有的鎖。。。。。。。。。)
更多詳情可以看:http://www.cnblogs.com/duanxz/p/4967042.html
public class Object{ public final native Class<?> getClass(); }
2.型別指標(指向物件 “元資料” 的指標)
instanceData(資料例項)
long, double放在一起
short/char放在一起(相同大小會放在一起)
padding (對齊填充,物件大小必須要8個位元組)
物件訪問定位:
垃圾回收:
判定物件為垃圾的演算法
1.引用計數法:
在物件中新增一個引用計數器,當有地方引用到這個物件的時候,引用計數器的值就+1,當引用失敗的時候,計數器的值就-1
-verbose:gc(簡單列印垃圾回收的日誌資訊)
-XX:+PrintGCDetails (詳細列印gc垃圾回收日誌資訊)
public class Main {
private Object instance;
public Main() {
//手動開闢20兆的空間
//1TB=1024GB 1GB=1024MB 1MB=1024KB 1KB=1024B 1B(位元組byte)=8b(位元bit)
//1MB(Mebibyte,兆位元組,百萬位元組,簡稱“兆”)=1024KB(千位元組)= 2^20 byte=1024*1024 byte
byte [] m=new byte[20*1024*1024];
}
public static void main(String[] args) {
Main m1=new Main();
Main m2=new Main();
m1.instance=m2;
m2.instance=m1;
m1=null;
//銷燬物件1
m2=null;
//銷燬物件2
System.gc();
//手動呼叫垃圾回收器
}
}
2.可達性分析演算法
從GCRoots節點出發,沿著引用鏈遍歷物件,為被遍歷的,便被判定為 垃圾(即物件沒有任何的引用指向它,就會被標記為垃圾物件)
可作為GCRoots的物件
1.1虛擬機器棧(這裡指虛擬機器棧中的區域性變量表)
1.2方法區的類屬型所引用的物件
1.3方法區中常量所引用的物件
1.4本地方法棧中引用的物件
回收垃圾:
1.標記-清除演算法:
效率問題
空間問題
標記出要回收的物件
複製演算法;
1.執行緒共享區:堆 (細分為:
新生代(
1.1 Eden 中文為伊甸園,建立一個物件,就會被扔到這裡,新建立的就會在這裡無憂無慮的生活,但也是死神垃圾回收器最喜歡光顧的地方
1.2 Survivor 存活區
1.3 Tenured Gen 養老區)
--------------------------------------------------------------------------------------------------------------------------
引用一段比喻:
JVM區域總體分兩類,heap區和非heap區。heap區又分:Eden Space(伊甸園)、Survivor Space(倖存者區)、Tenured Gen(老年代-養老區)。 非heap區又分:Code Cache(程式碼快取區)、Perm Gen(永久代)、Jvm Stack(java虛擬機器棧)、Local Method Statck(本地方法棧)。
HotSpot虛擬機器GC演算法採用分代收集演算法:
1、一個人(物件)出來(new 出來)後會在Eden Space(伊甸園)無憂無慮的生活,直到GC到來打破了他們平靜的生活。GC會逐一問清楚每個物件的情況,有沒有錢(此物件的引用)啊,因為GC想賺錢呀,有錢的才可以敲詐嘛。然後富人就會進入Survivor Space(倖存者區),窮人的就直接kill掉。
2、並不是進入Survivor Space(倖存者區)後就保證人身是安全的,但至少可以活段時間。GC會定期(可以自定義)會對這些人進行敲詐,億萬富翁每次都給錢,GC很滿意,就讓其進入了Genured Gen(養老區)。萬元戶經不住幾次敲詐就沒錢了,GC看沒有啥價值啦,就直接kill掉了。
3、進入到養老區的人基本就可以保證人身安全啦,但是億萬富豪有的也會揮霍成窮光蛋,只要錢沒了,GC還是kill掉。
分割槽的目的:新生區由於物件產生的比較多並且大都是朝生夕滅的,所以直接採用標記-清理演算法。而養老區生命力很強,則採用複製演算法,針對不同情況使用不同演算法。
非heap區域中Perm Gen中放著類、方法的定義,jvm Stack區域放著方法引數、局域變數等的引用,方法執行順序按照棧的先入後出方式。
--------------------------------------------------------------------------------------------------------------------------
) 方法區
2.執行緒獨享:棧 本地方法棧 程式計數器
複製演算法圖:
優化後的
標記整理清除演算法(用於老年代的垃圾回收)
分代收集演算法:
記憶體分新生代和老年代,對於新生代,垃圾回收率較高的,會採用複製演算法,對於老年代,記憶體回收率較低的,會採用標記清除演算法。
垃圾收集器之Serial收集器(適用於客戶端):
最基本,發展最悠久
單執行緒垃圾收集器
PraNew多執行緒收集器
Parallel Scavenge 收集器(適用於高併發情況)
採用複製演算法(新生代收集器)
多執行緒收集器
達到可控制的 吞吐量(cpu用於執行使用者程式碼的時間與cpu消耗的總時間的比值)
吞吐量=(執行使用者程式碼時間)/(執行使用者程式碼時間+垃圾回收所佔的時間)
-XX:MaxGFPauseMillis垃圾收集器停頓時間
-XX:CGTimeRatio吞吐量大小
CMS收集器Concurrent Mark Sweep(高併發標記清除,用於老年代)
併發收集器(邊扔邊打掃)
並行縮短等待時間
併發可以提高速度
工作過程
優點:併發收集,低停頓
缺點:佔用大量cpu資源, 無法處理浮動垃圾(打掃過一遍的垃圾你又給扔了) ,出現Concurrent Mode Failure (併發清理的回收垃圾池的記憶體區域分配過小),空間碎片 (由標記清除演算法導致)
G1收集器(收集器界的老大,面向服務端)
優勢:並行與併發,分代收集,空間整合,可預測的停頓
步驟:初始,併發,最終標記,篩選回收