垃圾收集器(一)

1.1 概述

垃圾收集器(Garbage Collection ,GC):Java語言中會自動對垃圾進行回收。可是GC須要完成它的功能是就必須思考:算法

  1. 那些內存須要回收?
  2. 何時回收?
  3. 如何回收

Java內存運行時區域的包括有,程序計數器、虛擬機棧、本地方法棧、Java堆、及方法區。其中:程序技術其、虛擬機棧、本地方法棧區域隨線程而生,隨線程而滅。棧中的棧幀隨着方法的進入和退出而有條不紊的執行着出棧和入棧操做。所以這幾個區域的內存分配和回收是具有肯定性的。Java堆和方法區則不同,一個接口中的多個實現類的內存可能不同,一個方法的多個分支須要的內存也不同,因此這部分的內存分配和回收都是動態的。spa

1.2 須要回收的內存

通常而言,在堆中存放着Java世界中幾乎全部的對象實例。垃圾收集器對內存是否須要回收的標準——對象是否被引用。線程

1.2.1 引用計數算法

給對象添加一個引用計數器,當一個地方應用它時,計數器就加1;當引用失效是,計數器減1。當計數器的值爲1時,則斷定該對象不可能在被引用。對象

其優勢:實現簡單、斷定效率高;接口

缺點:難以解決對象中之間互相循環引用的問題。內存

1.2.2 可達性分析算法

在主流的商用語言中,主要是採用可達性分析算法(Reachability Analysis)來判斷對象是否可達。思路:採用「GC Roots」的對象做爲起始點,從這些節點向下搜索,搜索所走過的路稱爲「引用鏈」,當一個對象同過引用鏈能夠和「GC Roots」鏈接是,則對象不可回收,不然回收對象。虛擬機

Java 語言中,可做爲GC Root的對象包括有如下幾種:it

  1. 虛擬機棧(棧幀中的本地變量表)中引用的對象;
  2. 方法區中靜態屬性的引用的對象;
  3. 方法區中常量引用的對象;
  4. 本地方法棧中JNI(即通常說的Native)引用的對象;

通常而言,就是定義的常量。io

1.2.3 引用

以可達性分析算法區分對象是否被引用仍是過於簡單了。對於某些對象,也許須要對象,當內存空間還足夠時,將其保留在內存中,不然進行垃圾收集。效率

所以,將引用在分爲:強引用(Strong Reference)、軟引用(Soft Reference)、弱引用(Weak Reference)、虛引用(Phantom Reference.

強引用:垃圾回收器永遠不會回收該對象,(形成內存泄漏的主要緣由之一);

軟引用:當內存充足時,對象不會被回收,不然回收該對象。一般適用於內存空間敏感的地方。內存不夠是,進行垃圾回收。回收以後若是尚未足夠的內存,會拋出內存溢出異常;

弱引用:當垃圾回收器運行時,不管是否內存足夠,會直接回收內存;

虛引用:一個對象是否有虛引用存在,徹底對其生存時間產生不了影響,也沒法經過虛引用來取得一個對象的實例。其存在的惟一目的是定位對象被垃圾收集的位置。

1.3 垃圾回收算法

1.3.1 標記-清除算法

好比教室若是要更換桌子,咱們能夠先遍歷一下那些桌子是壞並標記,而後在遍歷一下桌子是否有標記,把有標記的桌子擡出去。標記-清除算法顧名思義是先標記,再清除。這是最簡單的收集算法,容易實現。

缺點:1.須要遍歷兩遍,效率不高;

2).產生間斷性的內存碎片;

1.3.2 複製算法

複製算法是但咱們知道對象存活率較低時,能夠把還存活的對象格外放在一塊區域,而後將另外一區域的對象所有回收。

所以,把內存分爲一個較大的Eden空間和兩個較小的Survivor區間。HotSpot默認的二者比例數8:1

1.3.3 標記-整理算法

若是對象存活率較高時,能夠採用「標記-整理算法」。先將能夠回收的對象進行標記,而後讓全部可存活的對象向一端移動,直接清除邊界之外的內存。

1.3.4 分代收集算法

當前Java虛擬機大多采用分代收集算法。思想是,根據對象的存活週期的不一樣將內存分爲幾塊。通常講Java分爲新生代和老生代。通常而言,新生代有98%的對象是能夠被回收的,所這裏通常採用複製算法。老年代存活率比較高,能夠採用「標記-清除」或者「標記整理」法。

相關文章
相關標籤/搜索