c語言:css
java語言:java
c的垃圾回收是人工的,工做量大,可是可控性高。 java是自動化的,可是可控性不好,甚至有時會出現內存溢出的狀況, 內存溢出也就是jvm分配的內存中對象過多,超出了最大可分配內存的大小。
System.gc()用於調用垃圾收集器,在調用時,垃圾收集器將運行以回收未使用的內存空間。它將嘗試釋放被丟棄對象佔用的內存。 然而System.gc()調用附帶一個免責聲明,沒法保證對垃圾收集器的調用。 因此System.gc()並不能說是完美主動進行了垃圾回收。
做爲java程序員仍是頗有必要了解一下gc,這也是面試過程當中常常出現的一道題目。 咱們從三個角度來理解gc。 1jvm怎麼肯定哪些對象應該進行回收 2jvm會在何時進行垃圾回收的動做 3jvm究竟是怎麼清楚垃圾對象的
對象是否會被回收的兩個經典算法:引用計數法,和可達性分析算法。
簡單的來講就是判斷對象的引用數量。實現方式:給對象共添加一個引用計數器,每當有引用對他進行引用時,計數器的值就加1,當引用失效,也就是不在執行此對象是,他的計數器的值就減1,若某一個對象的計數器的值爲0,那麼表示這個對象沒有人對他進行引用,也就是意味着是一個失效的垃圾對象,就會被gc進行回收。 可是這種簡單的算法在當前的jvm中並無採用,緣由是他並不能解決對象之間循環引用的問題。 假設有A和B兩個對象之間互相引用,也就是說A對象中的一個屬性是B,B中的一個屬性時A,這種狀況下因爲他們的相互引用,從而是垃圾回收機制沒法識別。
由於引用計數法的缺點有引入了可達性分析算法,經過判斷對象的引用鏈是否可達來決定對象是否能夠被回收。可達性分析算法是從離散數學中的圖論引入的,程序把全部的引用關係看做一張圖,經過一系列的名爲GC Roots的對象做爲起始點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈。當一個對象到 GC Roots 沒有任何引用鏈相連(就是從 GC Roots 到這個對象不可達)時,則證實此對象是不可用的。
如圖:程序員
1會在cpu空閒的時候自動進行回收 2在堆內存存儲滿了以後 3主動調用System.gc()後嘗試進行回收
三如何回收 如何回收說的也就是垃圾收集的算法。 算法又有四個:標記-清除算法,複製算法,標記-整理算法,分代收集算法. 1 標記-清除算法。 這是最基礎的一種算法,分爲兩個步驟,第一個步驟就是標記,也就是標記處全部須要回收的對象,標記完成後就進行統一的回收掉哪些帶有標記的對象。這種算法優勢是簡單,缺點是效率問題,還有一個最大的缺點是空間問題,標記清除以後會產生大量不連續的內存碎片,當程序在之後的運行過程當中須要分配較大對象時沒法找到足夠的連續內存而形成內存空間浪費。
執行如圖:面試
2複製算法。 複製將可用內存按容量劃分爲大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活着的對象複製到另一塊上面,而後再把已使用過的內存空間一次清理掉。這樣使得每次都是對其中的一塊進行內存回收,內存分配時也就不用考慮內存碎片等複雜狀況。只是這種算法的代價是將內存縮小爲原來的一半。
複製算法的執行過程如圖:複製收集算法在對象存活率較高時就要執行較多的複製操做,效率將會變低。更關鍵的是,浪費了一半的空間。算法
標記-整理算法: 標記整理算法與標記清除算法很類似,但最顯著的區別是:標記清除算法僅對不存活的對象進行處理,剩餘存活對象不作任何處理,形成內存碎片;而標記整理算法不只對不存活對象進行處理清除,還對剩餘的存活對象進行整理,從新整理,所以其不會產生內存碎片。
標記整理算法的做用示意圖以下: swift
分代收集算法: 分代收集算法是一種比較智能的算法,也是如今jvm使用最多的一種算法,他自己其實不是一個新的算法,而是他會在具體的場景自動選擇以上三種算法進行垃圾對象回收。
那麼如今的重點就是分代收集算法中說的自動根據具體場景進行選擇。這個具體場景究竟是什麼場景。 場景其實指的是針對jvm的哪個區域,1.7以前jvm把內存分爲三個區域:新生代,老年代,永久代。
瞭解過場景以後再結合分代收集算法得出結論: 一、在新生代中,每次垃圾收集時都發現有大批對象死去,只有少許存活,那就選用複製算法。只須要付出少許存活對象的複製成本就能夠完成收集。 二、老年代中由於對象存活率高、沒有額外空間對他進行分配擔保,就必須用標記-清除或者標記-整理。
總結:jvm
注意: 在jdk8的時候java廢棄了永久代,可是並不意味着咱們以上的結論失效,由於java提供了與永久代相似的叫作「元空間」的技術。 廢棄永久代的緣由:因爲永久代內存常常不夠用或發生內存泄露,爆出異常java.lang.OutOfMemoryErroy。元空間的本質和永久代相似。不過元空間與永久代之間最大的區別在於:元空間並不在虛擬機中,而是使用本地內存。也就是不侷限與jvm可使用系統的內存。理論上取決於32位/64位系統可虛擬的內存大小。