java 內存回收和回收機制的算法

java是不會出現內存泄露的,你可以在new完對象之後將其進行顯性的釋放,調用finalize(),儘管new對象沒事的,反正都可以回收掉,這是我們經常聽到的,前幾天聽我以同學說,課本上竟然寫着java內存不會發生泄露,今天就想到來寫一篇關於java內存回收方面的博客。

首先這些問題的緣由就是java給廣大程序員的一個許諾,我有垃圾回收機制,有了垃圾回收機制就一定不會內存泄露??

先從內存泄露這個概念來說吧,在程序的運行期間會不斷的分配內存,當非配的內存空間不再被使用的時候但是沒有被回收回來這就是內存泄露。

對象在內存中的狀態,有三種狀態,1.可到達狀態,2.可恢復狀態3.不可到達狀態。

JVM的垃圾回收機制採用的是有向圖的方式來進行管理內存中的對象,可以比較方便的解決一些比較複雜的引用問題,也是根據有向圖的機制來進行,



通過上面的圖我們可以看出,三個引用P1,P2,P3的指向分別爲Kevin,無指向,Rain,其中Kevin有一個路徑指向,Rain有兩個路徑指向,但是sunny沒有引用指向它,失去了引用,所以sunny是不可達狀態就會被垃圾回收機制回收,其中,當其喪失引用之後並不是立即成爲了不可達狀態而是首先作爲可恢復狀態,系統會調用finalize()進行資源清理,如果該方法使得該對象出現了一個以上的引用,那麼其再次成爲了可到達狀態。垃圾回收機制判斷一個對象是否可回收的標準就是該對象現在是否還被引用。

對象的引用類型

對象爲引用類型有四種,分別爲強引用,弱引用,軟引用,虛引用。不同的引用對對象的生命週期有着很大的影響,首先是強引用,也是我們使用最多的引用方式也就是創建一個對象,並把這個對象賦給一個引用,被強引用的java對象永遠不會被回收,雖然有一些我們已經是不再使用了,但是它還是存在內存之中的,所以強類型成了導致java內存泄露的主要原因,其它三種引用可能是我們再做一些小型的開發過程中很少用到的,對於這三類來說無非就是聲明週期比強引用的要短,軟引用,通過SoftReference類來進行實現,當內存空間足夠的時候,它和強類型是沒有什麼區別的,是不會被回收的,但是當空間不足的時候就會被回收掉,但是強類型是不會被回收的,這就會導致整個程序crash,所以我們在需要new出很多對象的地方使用軟引用,來防止程序崩潰,來提升用戶體驗,但是不足的地方就是其中的對象是否已經被釋放掉了我們是不知道的,這就會導致出現空指針引用,但是我們在後面添加一個判斷語句來進行判斷是否爲null。

下面展現一個軟引用的代碼實例

class Person{
	    String name;
	    public Person(String name){
		this.name = name;
	    }
	}
	public class Test (){
	    public static void main(String []args){
		SoftReference<Person>[]people = new SoftReference[100000];
		for (int i = 0;i <people.length;i++){
		    people[i]= new SoftReference<Person>(new Person("snowsea"));
		}
		System.out.println(people[2].get());
	    }
	}


我們得到的輸出值是null,但是如果是用強類型的話我們得到的就是整個程序crash了。對於弱引用就是採用弱引用的就和失去引用的一樣處在可恢復狀態,在垃圾機制回收的時候就會被立即回收。

內存泄露,在這方面java做的不得不說確實要比其他語言好,拿C++來說,對於其中的喪失引用的對象,我們要自己顯示的調用代碼進行回收,通過下面這個圖看一下



c++中的對象一旦未正確釋放,喪失了引用之後就會導致該對象處於一個不可達的狀態,這就會使得我們無法找到,想釋放也無能爲力,通過代碼,我們可以將該對象存在的空間交給系統也就將其釋放掉,但是java的垃圾回收機制使得每一個對象都處在一個被監控的狀態,JVM可以回收這個方框中的任何對象。

自己之前涉及到一點關於垃圾回收機制設計的算法問題,大致有以下的幾種方式,從以下幾個角度來進行分析,1.cpu串行回收,也就只有一個cpu來執行這個操作,第二就是並行回收,就是有多個cpu同時運作進行垃圾回收,第一中方式效率肯定要比第二種方式要低一些,但是第二種方式就會出現內存碎片的問題,應爲回收的過程是由多個cpu來進行處理的,主要並行回收,也並不是說這幾個cpu同時進行,而是多個cpu間歇性的運作,也就是這個執行一段時間,另一個接着去執行,在設計上的複雜度比較大,而且會出現內存碎片,內存碎片有兩種一種是內部碎片,另一種是外部碎片,外部碎片是未被分配給確定的對象,但是卻無法使用的,由於空間比較小,內部碎片就是在已分配的空間中存在的程序不可利用的空間,並行就容易產生外部碎片。

2執行方式 併發執行應用程序停止執行,併發執行容易和當前正在運行的程序產生衝突,設計難度比較大,應用程序停止對用戶的體驗可能不夠好,在設計上要比並發簡單很多。3.回收方式  壓縮,不壓縮,和複製  壓縮就是先將當前可到達的對象搬遷在一起,然後釋放掉不可到達的,不壓縮就是對其內存空間進行遍歷,然後釋放掉不可到達到的,這中方式的缺陷就是容易產生外部內存碎片,複製就是將可到達的複製出一份,然後將原來的釋放掉,缺陷就是比較喫內存。


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