一、JVM運行時數據區域
1.線程共享區域:堆(存放對象實例以及數組)、元空間(存儲已被虛擬機加載的類信息、常量、靜態變量、即使吧編譯器編譯後的代碼等數據,又稱Non-Heap(非堆))
2.線程私有區域:虛擬機棧(局部變量表)、程序計數器、本地方法棧
堆空間的基本結構
-
eden(8/10)
-
s0(from survivor)(1/3)
-
s1(to survivor)(1/3)
-
tentired(佔堆空間大小的2/3)
其中eden、s0、s1屬於新生代,tentired屬於老年代。
堆內存分配策略:
- 對象優先在eden區分配
- 大對象直接進入 老年代
- 長期存活的對象將進入老年代
二、ClassLoader(類加載器)
1.主要作用:從系統外獲得Class二進制數據流,它是Java核心組件,所有的Class都是由Classloader負責加載的,Classloader負責通過將Class文件裏的二進制數據流裝載進系統,然後交給Java虛擬機進行連接、初始化等操作。
2.種類:
1)BootStrapClassLoader:C++編寫,負責加載核心庫 java.*
2)ExtClassloader:Java編寫,加載拓展庫 javax.*
3)AppClassloader:Java編寫,加載程序所在目錄
4)自定義Classloader:Java編寫,定製化加載
3.類加載器的雙親委派機制
- 定義:在類加載的時候,系統會首先判斷當前類是否被加載過。已經加載的類會直接返回,否則纔會被加載。加載的時候 ,**首先會把該請求委派該父類加載器的loadClass()處理,因此所有的請求最終都會應該傳到頂層的啓動類加載器BootstrapClassLoader中。**當父類加載器無法處理時,才由自己處理。
1)自底向上檢查類是否已經加載 CustomClassloader->AppClassloader->ExtClassloader->BootStrapClassloader
2)自頂向下嘗試加載類
三、如何判斷對象已將死亡?
-
引用計數法:
1)通過判斷對象的引用數量來決定對象是否可以被回收;
2)每個對象實例都有一個引用計數器,被引用則+1,完成引用則-1;
3)任何引用計數爲0的對象實例都可以被當作垃圾回收 -
優缺點
1)優點:執行效率高,程序執行受影響較小
2)缺點:無法檢測出循環引用的情況,會導致內存泄漏 -
可達性分析算法:通過一系列稱爲“GC Root”的對象爲起點,從這些節點開始向下搜索,走過的路徑稱爲引用鏈。當一個對象到GC Root沒有任何引用鏈相連的話,則證明該對象是不可達的,會被回收掉。
1)可以作爲GC Root的對象:
a.虛擬機棧中引用的對象(棧幀中的局部變量表)
b.方法區中的常量引用的對象
c.方法區中類靜態屬性引用的對象
d.本地方法棧中的引用對象
e.活躍線程的引用對象
四、垃圾回收算法
-
標記-清除算法(Mark and Sweep):算法分“標記”和“清除”兩個階段:首先標記出所有需要回收的對象,在標記完成後統一回收所有被標記的對象。
1)缺點:
a.會產生大量不連續的內存碎片
b.執行效率低 -
複製算法(Copying):
1)分爲對象面和空閒面;
2)對象在對象面上創建;
3)存活的對象被從對象面複製到空閒面;
4)將對象面所有的對象內存清除2.2 優點:
1)解決碎片化問題;
2)順序分配內存,簡單高效;
3)適用於存活率低的場景 -
標記-整理算法(Compacting)
1)避免內存的不連續性;
2)不用設置兩塊內存互換;
3)適用於存活率低的場景 -
分代收集算法(Generational Collector)
1)根據對象存活週期的不同將內存劃分爲幾塊。一般將Java Heap分爲新生代和老年代,這樣我們就可以根據各個年代的特點選擇適合的垃圾收集算法。
4.1 目的:提高JVM回收效率
4.2 GC的分類:
1)Minor GC(複製->清除->交換):Minor GC又稱爲新生代GC : 指的是發生在新生代的垃圾收集。因爲Java對象大多都具備朝生夕滅的特性, 因此Minor GC(採用複製算法)非常頻繁,一般回收速度也比較快。
2) Full GC:Full GC 又稱爲老年代GC或者Major GC.指發生在老年代的垃圾收集。出現了Major GC,經常會伴隨至少一次的Minor GC(並非絕對,在Parallel Scavenge收集器中就有直接進行Full GC的策略選擇過程)。Major GC的速度一般會比Minor GC慢10倍以上。
4.3 Stop-the-world
1) JVM由於要執行GC而停止了應用程序的執行;
2)任何一種GC算法中都會發生
3)多數GC優化提高減少Stop-the-world發生的時間來提高程序性能。
4.4 Safepoint
1)分析過程中對象引用關係不會發生變化的點;
2)產生Safepoint的地方:方法調用、循環跳轉、異常跳轉等
3)安全點的數量的得適中
五、垃圾收集器:
-
Serial收集器(-XX:+UseSerialIGC,複製算法)
1)單線程收集,進行垃圾收集時,必須暫停所有工作線程
2)簡單高效,Client模式默認的年輕代收集器 -
ParNew收集器(-XX:+UseParNewGC,複製算法)
1)多線程收集,其餘的行爲、特點和Serial收集器一樣
2)單核執行效率不如Serial收集器,在多核下執行纔有優勢 -
Parallel Scavenge收集器(-XX:+UseParallelGC,複製算法)
1)比起關注用戶線程停頓的時間,更加關注系統的吞吐量
2)在多核下執行纔有優勢,Server模式下默認的年輕代收集器 -
Serial Old收集器(-XX:+UseSerialGC,標記-整理算法)
1)單線程收集,進行垃圾收集時,必須暫停所有工作線程
2)簡答高效,Client模式下默認的老年代收集器 -
Parallel Old收集器(-XX:+UseParallelGC,標記-整理算法)
1)多線程,吞吐量優先 -
CMS收集器(-XX:UseConcMarkSweepGC,標記-清除算法)
多線程執行,是老年代常使用的垃圾回收器
-
Garbage First收集器(-XX:+UseG1GC)
7.1 特點:
1)並行和併發;
2)分代收集
3)空間整合
4)可預測的停頓
7.2 G1收集器的運作步驟:
- 初始標記
- 併發標記
- 最終標記
- 篩選回收
六、Java中的四大引用
1.強引用(Strong Reference)
1)最普遍的引用:Object obj = new Object();
2)拋出OOM終止程序也不會回收具有強引用的對象
3)通過將對象設置爲null來弱化引用,使其被回收
2.軟引用(Soft Reference)
1)對象處在有用但非必須的狀態;
2)只有當內存空間不足時,GC會回收該引用對象的內存
3)可以用來實現高速緩存
String str = new String(“abc”);
SoftReference sr = new SoftReference<>();
3.弱引用(Weak Reference)
1)非必須的對象,比軟引用更弱一些;
2)GC時會被回收
3)被回收的概率也不大,因爲GC線程 優先級比較低;
4)適用於引用偶爾被使用 且不影響垃圾收集的對象
String str = new String(“abc”);
WeakReference wr = new WeakReference<>();
4.虛引用(PhantomReference)
1)不會決定對象的生命週期
2)任何時候都可能被垃圾收集器回收
3)跟蹤對象被垃圾收集回收的活動,起哨兵作用
4)必須和引用隊列ReferenceQueue一起使用
String str = new String(“abc”);
ReferenceQueue queue = new ReferenceQueue();
PhantomReference pr = new PhantomReference(str,queue);
七、調用System.gc()是否會立即執行垃圾回收?
答:**不會。**當我們調用System.gc()的時候,其實並不會馬上進行垃圾回收,甚至不一定會執行垃圾回收。當我們直接調用System.gc()只會把這次gc請求記錄下來,等到runFinalization=true的時候纔會先去執行GC,runFinalization=true之後會在允許一次system.gc()。之後在call System.gc()還會重複上面的行爲。