公衆号:知識淺談
為了不侵犯作者版權,選擇了轉載,我補充了很多自己的了解。
垃圾回收相關
- GC Root都有哪些?
- 垃圾回收器的基本原理
- 垃圾回收器不可以馬上回收記憶體
- 怎麼主動通知虛拟機進行垃圾回收
- java中會存在記憶體洩漏嗎
- minor gc運作的很頻繁可能是什麼原因引起的?
- minor gc運作的很慢有可能是什麼原因引起的?
- 垃圾回收的優點以及原理
- GC是什麼,為什麼要有GC?
- GC算法
GC Root都有哪些?
1、虛拟機棧中引用的對象
比如:各個線程被調用的方法中使用到的參數、局部變量等。
2、本地方法棧内JNI(通常說的本地方法)引用的對象
3、方法區中類靜态屬性引用的對象
比如:Java類的引用類型靜态變量
4、方法區中常量引用的對象
比如:字元串常量池(string Table) 裡的引用
5、所有被同步鎖synchronized持有的對象
6、Java虛拟機内部的引用。
基本資料類型對應的Class對象,一些常駐的異常對象(如:
NullPointerException、OutOfMemoryError) ,系統類加載器。
7、根據使用者所選用的垃圾收集器以及目前回收的記憶體區域不同,還可以有其他對象“臨時性”地加入,共同構成完整GC Roots集合。
垃圾回收器的基本原理
對于GC來說,當程式員建立對象時,GC就開始監控這個對象的位址、大小以及使用情況。通常,GC采用有向圖的方式記錄和管理堆(heap)中的所有對象。通過這種方式确定哪些對象是”可達的”,哪些對象是”不可達的”。當GC确定一些對象為”不可達”時,GC就有責任回收這些記憶體空間。
垃圾回收器不可以馬上回收記憶體
垃圾收集器不可以被強制執行,但程式員可以通過調研System.gc方法來建議執行垃圾收集。
記住,隻是建議。一般不建議自己寫System.gc,因為會加大垃圾收集工作量。
怎麼主動通知虛拟機進行垃圾回收
程式員可以手動執行System.gc(),通知GC運作,但是Java語言規範并不保證GC一定會執行。
java中會存在記憶體洩漏嗎
會存在記憶體洩漏。
說明:記憶體洩漏是指一個不再被程式使用的對象或變量還在記憶體中占有存儲空間。
Java garbage collector自動釋放哪些記憶體裡面程式不在需要的對象, 以此避免大多數的其他程式上下文的記憶體洩漏. 但是Java應用程式依舊會有相當的記憶體洩漏。
- 靜态集合類:如HashMap、LinkedList等等。如果這些容器為靜态的,那麼它們的生命周期與程式一緻,則容器中的對象在程式結束之前将不能被釋放,進而造成記憶體洩漏。簡單而言,長生命周期的對象持有短生命周期對象的引用,盡管短生命周期的對象不再使用,但是因為長生命周期對象持有它的引用而導緻不能被回收。
- 各種連接配接,如資料庫連接配接、網絡連接配接和IO連接配接等。在對資料庫進行操作的過程中,首先需要建立與資料庫的連接配接,當不再使用時,需要調用close方法來釋放與資料庫的連接配接。隻有連接配接被關閉後,垃圾回收器才會回收對應的對象。否則,如果在通路資料庫的過程中,對Connection、Statement或ResultSet不顯性地關閉,将會造成大量的對象無法被回收,進而引起記憶體洩漏。
- 變量不合理的作用域。一般而言,一個變量的定義的作用範圍大于其使用範圍,很有可能會造成記憶體洩漏。另一方面,如果沒有及時地把對象設定為null,很有可能導緻記憶體洩漏的發生。
- 内部類持有外部類,如果一個外部類的執行個體對象的方法傳回了一個内部類的執行個體對象,這個内部類對象被長期引用了,即使那個外部類執行個體對象不再被使用,但由于内部類持有外部類的執行個體對象,這個外部類對象将不會被垃圾回收,這也會造成記憶體洩露。
- 改變哈希值,當一個對象被存儲進HashSet集合中以後,就不能修改這個對象中的那些參與計算哈希值的字段了,否則,對象修改後的哈希值與最初存儲進HashSet集合中時的哈希值就不同了,在這種情況下,即使在contains方法使用該對象的目前引用作為的參數去HashSet集合中檢索對象,也将傳回找不到對象的結果,這也會導緻無法從HashSet集合中單獨删除目前對象,造成記憶體洩露。
minor gc運作的很頻繁可能是什麼原因引起的?
1、 産生了太多朝生夕滅的對象導緻需要頻繁minor gc
2、 新生代空間設定的比較小
minor gc運作的很慢有可能是什麼原因引起的?
1、 新生代空間設定過大。
2、 對象引用鍊較長,進行可達性分析時間較長。
3、 新生代survivor區設定的比較小,清理後剩餘的對象不能裝進去需要移動到老年代,造成移動開銷。
4、 記憶體配置設定擔保失敗,由minor gc轉化為full gc
5、 采用的垃圾收集器效率較低,比如新生代使用serial收集器
垃圾回收的優點以及原理
優點:由于有個垃圾回收機制,Java中的對象不再有"作用域"的概念,隻有對象的引用才有"作用域"。垃圾回收可以有效的防止記憶體洩露,有效的使用可以使用的記憶體。
原理;垃圾回收器通常是作為一個單獨的低級别的線程運作,不可預知的情況下對記憶體堆中已經死亡的或者長時間沒有使用的對象進行清楚和回收,程式員不能實時的調用垃圾回收器對某個對象或所有對象進行垃圾回收。回收機制有分代複制垃圾回收和标記垃圾回收,增量垃圾回收。
GC是什麼,為什麼要有GC?
GC算法
- 引用計數器的實作很簡單,對于一個對象A,隻要有任何一個對象引用了A,則A的引用計數器就加1,當引用失效時,引用計數器就減1。隻要對象A的引用計數器的值為0,則對象A就不可能再被使用。
- 标記-清除算法是現代垃圾回收算法的思想基礎。标記-清除算法将垃圾回收分為兩個階段:标記階段和清除階段。一種可行的實作是,在标記階段,首先通過根節點,标記所有從根節點開始的可達對象。是以,未被标記的對象就是未被引用的垃圾對象。然後,在清除階段,清除所有未被标記的對象。與标記-清除算法相比。
- 标記整理:首先通過根節點,标記所有從根節點開始的可達對象。是以,未被标記的對象就是未被引用的垃圾對象,整理階段就是把标記的對象移動到一側,之後清除掉其餘的的未标記的,這樣就解決了标記清楚造成的記憶體碎片化問題。
- 複制算法是一種相對高效的回收方法不适用于存活對象較多的場合如老年代将原有的記憶體空間分為兩塊,每次隻使用其中一塊,在垃圾回收時,将正在使用的記憶體中的存活對象複制到未使用的記憶體塊中,之後,清除正在使用的記憶體塊中的所有對象,交換兩個記憶體的角色,完成垃圾回收。