一、垃圾回收
1.如何判斷對象可以回收
(1)引用計數法
存在循環引用問題, Java未使用這種算法
在引用計數法中,每個對象都有一個引用計數器,記錄著指向該對象的引用數量。當引用計數器為零時,表示沒有任何引用指向該對象,該對象可以被釋放,回收其占用的內存。
(2)可達性分析法
根對象:肯定不能被垃圾回收的對象
2.Java引用類型
1.強引用
被GC-Root引用
2.軟引用
沒有被強引用, 垃圾回收時內存不夠,軟引用被回收
3.弱引用
沒有強引用,只要發生垃圾回收,弱引用會被回收掉
軟引用 弱引用也占用一定的內存,對 它兩進行釋放,通過引用隊列
4. 虛引用
必須配合引用隊列使用,虛引用對象被垃圾回收時,虛引用 自己放入引用隊列,由一個線程釋放內存
5.終結器引用
Object中有finallize方法,對象重寫finallize方法 ,并且沒有強引用 引用它,可以被當作垃圾回收
軟引用實例
弱引用實例
垃圾回收算法
1.標記清除算法
標記清除算法(Mark-Sweep Algorithm)是一種常見的垃圾回收算法,用于自動管理動態分配的內存空間。其原理如下:
標記階段(Mark):從根對象開始,通過引用鏈追蹤,標記所有的活動對象。標記過程中,將活動對象的標記位設置為有效狀態,表示這些對象是可達的,不會被回收。
清除階段(Sweep):在標記階段完成后,遍歷整個內存空間,將未被標記的對象視為垃圾對象,將其所占用的內存空間釋放,以便下次分配給新的對象使用。
優點:速度快
缺點:容易造成內存碎片
標記清除算法通過標記和清除的過程,將不再被使用的內存空間回收,以避免內存泄漏和內存碎片的問題。
然而,標記清除算法也存在一些缺點,如清除階段會產生內存碎片,可能會導致內存分配的效率降低。
2.標記整理算法
- 標記階段:
與其他垃圾回收算法一樣,標記-整理算法從根對象開始遍歷整個對象圖,標記所有與根對象可達的對象,即被引用的對象。 - 整理階段:
在整理階段,標記-整理算法會對內存空間進行整理,將所有存活的對象移動到一端,而未標記的對象則被認為是垃圾對象。
移動存活對象的過程中,標記-整理算法會保持存活對象之間的相對位置關系,從而確保所有存活對象在整理后仍然是連續的。 - 回收階段:
在整理階段完成后,標記-整理算法會回收并釋放未標記的垃圾對象所占用的內存空間,從而實現垃圾回收。
優點:沒有內存碎片
缺點:速度慢
3.復制算法
復制算法的基本思想是將內存空間劃分為兩個大小相等的區域,通常稱為"From"空間和"To"空間。在垃圾回收過程中,首先將所有存活的對象從"From"空間復制到"To"空間中,然后對整個"From"空間進行垃圾回收,將未復制的垃圾對象清理掉。在下次垃圾回收時,交換"From"空間和"To"空間的角色,繼續進行復制和回收操作。這樣,"From"空間和"To"空間的角色不斷交替,實現了垃圾對象的回收和內存空間的復用。
優點:不會產生碎片
缺點:需要占用雙倍內存
分代回收
新生代空間不足,觸發MinorGC,先標記
eden(伊甸園)滿了,采用復制算法將存活的對象復制到TO中,幸存的對象壽命+1
交換From和To
第二次垃圾回收
當對象壽命超過閾值(15),晉升到老年代
FullGC
老年代空間不足,先嘗試進行一次MinorGC ,之后空間任然不足,觸發FullGC
Stop the world 暫停其他線程,進行垃圾回收
4.垃圾回收器
4.1 串行垃圾回收器
- 單線程
- 堆內存較小 適合個人電腦
新生代:復制算法
老年代: 標記 + 整理 算法
4.2 吞吐量優先
- 多線程
- 堆內存較大,多核CPU
- 單位時間內,STW時間最短 0.2 0.2 = 0.4 只執行了兩次
多個垃圾回收線程并行執行,不允許用戶工作線程運行
4.3響應時間優先
- 多線程
- 堆內存較大,多核CPU
- 盡可能讓單次STW時間短 0.1 0.1 0.1 0.1 0.1 = 0.5
與用戶線程并發執行,在工作的同時用戶線程也能工作。工作代老年代
5. G1 垃圾回收器
5. 整體過程,分為三個部分
5.1 Young Collection
新生代內存緊張,放入幸存區
幸存區S有一部分晉升到老年區O
5.2 Young Collection + CM (并發標記)
初始標記: 標記根對象
并發標記: 從根對象觸發,順引用鏈找到其他標記對象(老年代占用比例達到一定閾值,進行并發標記)
5.3Mixed Collection混合收集
混合收集階段優先回收垃圾最多的區,不是收集所有老年代的垃圾 。目的暫停時間短
5.4 FullGC
不懂