廢話少說,直接開整:
第1組:JDK、JRE、JVM的關係JDK中包含JRE,也包括JDK,而JRE也包括JDK。
範圍關係:JDK>JRE>JVM。
具體見下圖:
第2組:.java檔案與.class檔案的關係這兩者的關係需要兩張圖才能說明白:
第3組:class檔案與JVM的關係JVM透過類載入機制,把class檔案裝載進JVM中,然後JVM解析class檔案的內容,於是就有了類載入過中的連結、初始化等。
第4組:類載入器關係一張圖來說明:
第5組:方法區、堆、棧之間到底有什麼關係直接上圖:
棧指向堆如果在棧幀中有一個變數,型別為引用型別,比如:
package com.tian.my_code.test;public class JvmCodeDemo { public Object testGC(){ int op1 = 10; int op2 = 3; Object obj = new Object(); Object result=obj; return result; }}
這時候就是典型的棧中元素obj指向堆中的Object物件,result的指向和obj的指向為同一個物件。
使用命令
javac -g:vars JvmCodeDemo.java
進行編譯,然後再使用
javap -v JvmCodeDemo.class >log.txt
然後開啟log.txt檔案
方法區指向堆方法區中會存放靜態變數,常量等資料。
如果是下面這種情況,就是典型的方法區中元素指向堆中的物件。
堆指向方法區方法區中會包含類的資訊,物件儲存在堆中,建立一個物件的前提是有對應的類資訊,這個類資訊就在方法區中。
第6組:Minor、Major、Full GC的關係Minor GC:發生在年輕代的 GC。
Minor GC是指從年輕代空間(包括 Eden 和 Survivor 區域)回收記憶體。當 JVM 無法為一個新的物件分配空間時會觸發Minor GC,比如當 Eden 區滿了。Eden區滿了觸發MinorGC,這時會把Eden區存活的物件複製到Survivor區,當物件在Survivor區熬過一定次數的MinorGC之後,就會晉升到老年代(當然並不是所有的物件都是這樣晉升的到老年代的),當老年代滿了,就會報OutofMemory異常。所有的MinorGC都會觸發全世界的暫停(stop-the-world),停止應用程式的執行緒,不過這個過程非常短暫。Major GC:發生在老年代的 GC。
Major GC清理Tenured區(老年代)。Full GC:新生代+老年代,比如 方法區引起年輕代和老年代的回收。
第7組:Survivor與Eden的關係對於這兩者,最重要的是要明白為什麼需要Survivor區?只有Eden不行嗎?
如果沒有Survivor,Eden區每進行一次Minor GC ,並且沒有年齡限制的話, 存活的物件就會被送到老年代。這樣一來,老年代很快被填滿,觸發Major GC(因為Major GC一般伴隨著Minor GC,也可以看做觸發了Full GC)。老年代的記憶體空間遠大於新生代,進行一次Full GC消耗的時間比Minor GC長得多。
執行時間長有什麼壞處?
頻發的Full GC消耗的時間很長,會影響大型程式的執行和響應速度。
可能你會說,那就對老年代的空間進行增加或者較少咯。
假如增加老年代空間,更多存活物件才能填滿老年代。雖然降低Full GC頻率,但是隨著老年代空間加大,一旦發生Full GC,執行所需要的時間更長。
假如減少老年代空間,雖然Full GC所需時間減少,但是老年代很快被存活物件填滿,Full GC頻率增加。
所以Survivor的存在意義,就是減少被送到老年代的物件,進而減少Full GC的發生,Survivor的預篩選保證,只有經歷16 次Minor GC還能在新生代中存活的物件,才會被送到老年代。
第8組:引用計數法和可達性分享演算法的關係引用計數法給物件新增一個引用計數器,每當一個地方引用它object時計數加1,引用失去以後就減1,計數為0說明不再引用
優點:實現簡單,判定效率高缺點:無法解決物件相互迴圈引用的問題,物件A中引用了物件B,物件B中引用物件A。public class A { public B b; }public class B { public C c; }public class C { public A a; }public class Test{ private void test(){ A a = new A(); B b = new B(); C c = new C(); a.b=b; b.c=c; c.a=a; }}
可達性分析演算法當一個物件到GC Roots沒有引用鏈相連,即就是GC Roots到這個物件不可達時,證明物件不可用。
GC Roots種類:
❝
Java 執行緒中,當前所有正在被呼叫的方法的引用型別引數、區域性變數、臨時值等。也就是與我們棧幀相關的各種引用。所有當前被載入的 Java 類。Java 類的引用型別靜態變數。執行時常量池裡的引用型別常量(String 或 Class 型別)。JVM 內部資料結構的一些引用,比如 sun.jvm.hotspot.memory.Universe 類。用於同步的監控物件,比如呼叫了物件的 wait() 方法。
❞
第9組:物件的引用型別的關係強引用:User user=new User();我們開發中使用最多的物件引用方式。特點:我們平常典型編碼Object obj = new Object()中的obj就是強引用。透過關鍵字new建立的物件所關聯的引用就是強引用。當JVM記憶體空間不足,JVM寧願丟擲OutOfMemoryError執行時錯誤(OOM),使程式異常終止,也不會靠隨意回收具有強引用的“存活”物件來解決記憶體不足的問題。對於一個普通的物件,如果沒有其他的引用關係,只要超過了引用的作用域或者顯式地將相應(強)引用賦值為 null,就是可以被垃圾收集的了,具體回收時機還是要看垃圾收集策略。軟引用:SoftReference<Object> object=new SoftReference<Object>(new Object());特點:軟引用透過SoftReference類實現。軟引用的生命週期比強引用短一些。只有當 JVM 認為記憶體不足時,才會去試圖回收軟引用指向的物件:即JVM 會確保在丟擲 OutOfMemoryError 之前,清理軟引用指向的物件。軟引用可以和一個引用佇列(ReferenceQueue)聯合使用,如果軟引用所引用的物件被垃圾回收器回收,Java虛擬機器就會把這個軟引用加入到與之關聯的引用佇列中。後續,我們可以呼叫ReferenceQueue的poll()方法來檢查是否有它所關心的物件被回收。如果佇列為空,將返回一個null,否則該方法返回佇列中前面的一個Reference物件。應用場景:軟引用通常用來實現記憶體敏感的快取。如果還有空閒記憶體,就可以暫時保留快取,當記憶體不足時清理掉,這樣就保證了使用快取的同時,不會耗盡記憶體弱引用:WeakReference<Object> object=new WeakReference<Object> (new Object();ThreadLocal中有使用.弱引用透過WeakReference類實現。弱引用的生命週期比軟引用短。在垃圾回收器執行緒掃描它所管轄的記憶體區域的過程中,一旦發現了具有弱引用的物件,不管當前記憶體空間足夠與否,都會回收它的記憶體。由於垃圾回收器是一個優先順序很低的執行緒,因此不一定會很快回收弱引用的物件。弱引用可以和一個引用佇列(ReferenceQueue)聯合使用,如果弱引用所引用的物件被垃圾回收,Java虛擬機器就會把這個弱引用加入到與之關聯的引用佇列中。應用場景:弱應用同樣可用於記憶體敏感的快取。虛引用:幾乎沒見過使用, ReferenceQueue 、PhantomReference。第10組:垃圾回收演算法的關係標記-清除演算法第一步:就是找出活躍的物件。我們反覆強調 GC 過程是逆向的, 根據 GC Roots 遍歷所有的可達物件,這個過程,就叫作標記。
第二步:除了上面標記出來的物件以外,其餘的都清楚掉。
缺點:標記和清除效率不高,標記和清除之後會產生大量不連續的記憶體碎片複製演算法新生代使用,新生代分中Eden:S0:S1= 8:1:1,其中後面的1:1就是用來複制的。
當其中一塊記憶體使用完了,就將還存活的物件複製到另外一塊上面,然後把已經使用過的記憶體空間一次 清除掉。
一般物件分配都是進入新生代的eden區,如果Minor GC還存活則進入S0區,S0和S1不斷物件進行復制。物件存活年齡最大預設是15,大物件進來可能因為新生代不存在連續空間,所以會直接接入老年代。任何使用都有新生代的10%是空著的。
缺點:物件存活率高時,複製效率會較低,浪費記憶體。標記整理演算法它的主要思路,就是移動所有存活的物件,且按照記憶體地址順序依次排列,然後將末端記憶體地址以後的記憶體全部回收。 但是需要注意,這只是一個理想狀態。物件的引用關係一般都是非常複雜的,我們這裡不對具體的演算法進行描述。我們只需要瞭解,從效率上來說,一般整理演算法是要低於複製演算法的。這個演算法是規避了記憶體碎片和記憶體浪費。
讓所有存活的物件都向一端移動,然後直接清理掉端邊界以外的記憶體。
從上面的三個演算法來看,其實沒有絕對最好的回收演算法,只有最適合的演算法。
第11組:垃圾收集器之間有什麼關係「新生代收集器」:Serial、ParNew、Parallel Scavenge
「老年代收集器」:CMS、Serial Old、Parallel Old
「整堆收集器」:G1,ZGC(因為不涉年代不在圖中)