首先給你們講一個梗,爲何Java程序員愈來愈多,而C++程序員愈來愈少呢?—— 那還不是由於不用管理內存啊程序員
在C++中,本身new的對象,在不用的時候須要手動釋放。而在Java裏,你能夠釋放你的雙手,將這項工做交給JVM本身管理。在JVM裏面,這種機制叫作垃圾回收(Garbage Collection)機制。
算法
ps:本文不涉及垃圾收集器,主要是講垃圾回收的思路。cdn
Java的變量一共存儲在三個地方、方法區、堆、棧對象
主要存放常量,靜態常量、常量池,在程序編譯的時候,這塊內存就已經被分配出來了,伴隨程序的一輩子。blog
是JVM管理的內存最大的一塊,存放全部的實例對象,也是垃圾收集器管理的主要區域。也稱爲「GC堆」生命週期
當方法被執行的時候,方法內部的局部變量就會被存儲在棧裏,當方法執行完畢的時候,剛剛存儲的局部變量會被自動釋放。ip
前面說到垃圾收集器管理的是堆,在回收以前,一般須要判斷這個對象是不是存活的。內存
遍歷對象,當這個對象被其餘對象引用的時候計數器就加1,當引用失效的時候,計數器減1。當對象的計數器爲0時,則表示該對象沒有被引用。這種方法效率很高,可是沒法解決互相引用的問題。所以主流JVM都未採用這種方法。虛擬機
這一算法的思想是從GC Roots做爲起始點,從這些節點往下搜索,搜索的路徑叫作引用鏈,當一個對象沒有任何引用鏈能夠到GC ROOT的時候,則證實該對象是不可用的。通常想要宣告一個對象死亡,至少要經歷兩次標記,即標記-篩選-標記。 it
不足:
將可用內存分爲兩塊,每次只使用其中的一塊。一塊內存使用完的時候,將存活下來的對象複製到另外一塊中,再清除這一塊內存。這樣就沒什麼內存碎片可言了。
效率高,解決了內存碎片的問題。
複製-收集算法,在對象存活率高的狀況下,要進行屢次複製,效率比較低。因此說爲此提出了「標記-整理」算法。
標記過程同上,而後讓全部存活的對象移動到另外一端,而後清理掉邊界外的內存。
分代收集算法比較常見,通常把堆分爲新生代和老年代,這樣能夠根據各個年代的特色採用適當的算法。
在JDK1.2以後,Java對引用的概念進行了擴充,將引用分爲強引用(Strong Reference)、軟引用(Soft Reference)、弱引用(Weak Reference)、虛引用(Phantom Reference)四種,這四種引用強度依次逐漸減弱。
就是指在程序代碼之中廣泛存在的,例如new出來的對象,只要強引用還在,該對象就不會被回收。
用來描述一些還有用但並不是必須的對象。在內存即將溢出以前,垃圾收集器會將這些對象進行回收。
用戶描述非必須對象的。不管當前內存是否足夠,隨時都有可能被回收。
虛引用不會影響該對象都生命週期,只會在該對象被回收的適合得到一個系統通知。