[jvm解析系列][三]Java的垃圾回收(一)如何鑑別垃圾,四種引用類型

垃圾回收就想垃圾車,每次天亮就會沿着街區開一圈,把垃圾都帶走。

有的區域不需要這種垃圾車,也許它們不造垃圾吧,作爲一箇中級圖釘我對這種地區很無奈,但是它們就是很少有垃圾甚至沒有垃圾。首先應該是程序計數器,這玩意要什麼垃圾回收,我都不用講。下一個應該是虛擬機棧本地方法棧,棧幀的進出都受到控制,誰的垃圾誰帶走,在進門的時候就算清楚了你要用多少內存,最後你再全部帶走一點垃圾也不剩也不需要。(還有一個原因,是上述三個區域都是線程私有的,當線程撤退的時候把垃圾也都帶走了)

那麼根據第一章講的,我們還剩幾個區域?不記得就回去看吧^_^

還剩方法區(又稱永久代)java堆。也就是說只剩這兩個區需要垃圾回收了,垃圾佬表示很興奮啊,終於有垃圾收了。(雖然叫永久代,但是現在永久代也是回收垃圾的,只是垃圾的回收率低,並且條件十分苛刻)

那麼什麼是垃圾呢?垃圾如何定義呢?

嗯,在我們的概念中,不要的東西就是垃圾。在程序中如何確定一個對象我們不用了呢?,引用計數法,也就是每當該對象被引用時+1,被去引用時-1,到引用爲0的時候也就是該對象變垃圾的時候。嘿嘿嘿,我又瞎說了,沒錯是有這麼個用法,但是主流jvm一個都沒有使用這種方法定義垃圾的!

爲什麼呢?這個方法不是挺好的麼?

我舉個例子,如果我有

A a = new A();

 B b = new B();

a.b = b;

b.a = a;

這樣的情況下是不相互調用了?如果看不懂沒關係我畫幅圖給你

你矇蔽了嗎,是不是a和b對象直接就這樣泄漏了,我的媽,你的android如果用這種方式定義垃圾你是不是半天就得重啓一回防止累計下來的大量的內存泄漏呢?

所以我們的jvm沒有選擇引用計數算法,我們採用了可達性分析算法

在大多數商用的有垃圾回收的語言中多數都是採用這個算法的。簡單的說來就是從某一個GC Roots開始往下找引用,沒找到的就是垃圾。具體請看圖:


圖一帖上來打架都應該清楚了。1和2是垃圾,要回收。這個就是可達性分析算法。那麼1說了:“憑什麼root可以作爲GC Roots”而我不行!“2跟着附和:”這中間肯定有不可告人的“某圖釘:”py交易“。

其實並不是這樣,GC roots是有要求的,我們來分析一下,我們說一個對象不是垃圾,肯定我們是能得到的,我們在寫程序的時候什麼類型是可以在任何地方都能得到的呢?

1、虛擬機棧中引用的對象(即我在寫方法的時候A a =new A(),在方法沒結束的時候就是a就是可以作爲root使用的)

2、方法區中類靜態屬性(所以啊,我們應該少用類的靜態屬性,不然內存回收不了)

3、方法去中常量引用的對象

4、本地方法棧中JNI引用的對象

當一個類型是上述四個中的一個的時候,能跟他攀上關係的對象都不會被回收。

但是!後來改革了你知道嗎?(四種引用強度)原本的時候攀上一個大佬就高枕無憂了,但是在jdk1.2之後這些對象引起了重視被改革了。

號外號外!一號文件規定以後引用不再是boolean類型了,不再是有或者沒有的問題了~

它變成了四類引用

1、強引用

強引用是大家最常見的引用,他是jvm必不可少的,當強引用過多時寧願oom也不回收內存,最常見的應該就是new出來的對象了。

2、軟引用

軟引用如果jvm不缺內存的話不會回收,一旦缺少內存就會回收軟引用而不是報oom。SoftReference一般都是軟引用

3、弱引用

弱引用更不用說了,只要被jvm掃描到了立即回收。WeakReference一般都是軟引用

4、虛引用

虛引用。。。這玩意一不小心就沒了,至於他爲什麼和弱引用分開是因爲他有特殊的機制,在jvm回收內存的時候如果這個對象是虛引用,必須把這個虛引用放在引用隊列裏,如果引用隊列裏有一個虛引用說明這個對象要掛了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章