Java引用詳解

原文連接:https://blog.csdn.net/sunxianghuang/article/details/52267282html

https://www.cnblogs.com/yw-ah/p/5830458.htmljava

強引用(Strong Reference)

強引用是指在程序代碼中廣泛存在的,相似「Object obj=new Object()」這類的引用,只要強引用還存在,垃圾收集器永遠不會回收掉被引用的對象。this

public class StrongReferenceTest {
private static class BiggerObject{//佔用空間的一個大對象
public int[] values;
public String name;
public BiggerObject(String name){
this.name=name;
values=new int[1024];
}
}
public static void main(String[] args) {
int count=10000;//對象的個數,保證使得堆內存溢出
BiggerObject[] values=new BiggerObject[count];
for(int i=0;i<count;i++){
values[i]=new BiggerObject("Object-"+i);
}
for(int i=0;i<10;i++){
System.out.println(values[i].name);
} 
} 
}

輸出:spa

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid668.hprof ...
Heap dump file created [13980085 bytes in 0.181 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at StrongReferenceTest$BiggerObject.<init>(StrongReferenceTest.java:8)
    at StrongReferenceTest.main(StrongReferenceTest.java:15)

 

由於垃圾收集器沒法回收強引用關聯着的對象,從而致使堆內存溢出。.net

軟引用(Soft Reference)

用來描述一些還有用並不是必要的對象。對於軟引用關聯着的對象,在系統將要發生內存溢出異常以前,將會把這些對象列入回收範圍進行第二次回收。若是此次回收尚未足夠的內存,纔會拋出內存溢出異常。JDK 1.2以後,提供了SoftReference類來實現軟引用。code

import java.lang.ref.SoftReference;

public class SoftReferenceTest {
private static class BiggerObject{//佔用空間的一個大對象
public int[] values;
public String name;
public BiggerObject(String name){
this.name=name;
values=new int[1024];
}
}
public static void main(String[] args) {
int count=100000;//對象數量爲100000,保證使得堆內存溢出
SoftReference[] values=new SoftReference[count];
for(int i=0;i<count;i++){
values[i]=new SoftReference<BiggerObject>(new BiggerObject("Object-"+i));
}
System.out.println(((BiggerObject)(values[values.length-1].get())).name);
for(int i=0;i<10;i++){
System.out.println(((BiggerObject)(values[i].get())).name);
} 
} 
}

輸出:htm

Object-99999
Exception in thread "main" java.lang.NullPointerException
    at SoftReferenceTest.main(SoftReferenceTest.java:21)

 

第一行輸出說明,使用軟引用後,本來因爲堆內存溢出而沒法正常執行的代碼段「正常的」執行成功;對象

可是,當咱們訪問早期建立的那些對象時,卻報java.lang.NullPointerException異常,說明早期建立的對象已經被垃圾收集器回收了。blog

import java.lang.ref.SoftReference;

public class SoftReferenceTest {
private static class BiggerObject{//佔用空間的一個大對象
public int[] values;
public String name;
public BiggerObject(String name){
this.name=name;
values=new int[1024];
}
}
public static void main(String[] args) {
int count=100;//對象數量改成100,保證堆內存不會溢出
SoftReference[] values=new SoftReference[count];
for(int i=0;i<count;i++){
values[i]=new SoftReference<BiggerObject>(new BiggerObject("Object-"+i));
}
System.gc();//強制進行垃圾回收
System.out.println(((BiggerObject)(values[values.length-1].get())).name);
for(int i=0;i<10;i++){
System.out.println(((BiggerObject)(values[i].get())).name);
} 
} 
}

輸出:內存

Object-99

Object-0

Object-1

Object-2

Object-3

Object-4

Object-5

Object-6

Object-7

Object-8

Object-9

 

當堆內存足夠時,即便咱們強制進行垃圾回收,軟引用關聯着的對象也不會被回收。

弱引用(WeakReference)

弱引用也是用來描述非必要對象的,可是他的強度比軟引用更弱一些,被軟引用關聯的對象只能生存到下一次垃圾收集發生以前。當垃圾收集器工做時,不管當前內存是否足夠,都會回收掉只被弱引用關聯的對象。JDK 1.2以後,提供了WeakReference類來實現弱引用。

public class WeakReferenceTest {
private static class BiggerObject{//佔用空間的一個大對象
public int[] values;
public String name;
public BiggerObject(String name){
this.name=name;
values=new int[1024];
}
}
public static void main(String[] args) {
int count=10000;//對象數量爲10000,保證使得堆內存溢出
WeakReference[] values=new WeakReference[count];
for(int i=0;i<count;i++){
values[i]=new WeakReference<BiggerObject>(new BiggerObject("Object-"+i));
} 
System.out.println(((BiggerObject)(values[values.length-1].get())).name);
for(int i=0;i<10;i++){
System.out.println(((BiggerObject)(values[i].get())).name);
} 
} 
}

輸出:

Object-9999
Exception in thread "main" java.lang.NullPointerException
    at WeakReferenceTest.main(WeakReferenceTest.java:22)

輸出結果,與軟引用相同。

public class WeakReferenceTest {
private static class BiggerObject{//佔用空間的一個大對象
public int[] values;
public String name;
public BiggerObject(String name){
this.name=name;
values=new int[1024];
}
}
public static void main(String[] args) {
int count=100;//對象數量改成100,保證堆內存不會溢出
WeakReference[] values=new WeakReference[count];
for(int i=0;i<count;i++){
values[i]=new WeakReference<BiggerObject>(new BiggerObject("Object-"+i));
} 
System.out.println(((BiggerObject)(values[values.length-1].get())).name);
for(int i=0;i<10;i++){
System.out.println(((BiggerObject)(values[i].get())).name);
} 
} 
}

輸出:

Object-99
Object-0
Object-1
Object-2
Object-3
Object-4
Object-5
Object-6
Object-7
Object-8
Object-9

 

當堆內存夠用時,正常輸出。

public class WeakReferenceTest {
private static class BiggerObject{//佔用空間的一個大對象
public int[] values;
public String name;
public BiggerObject(String name){
this.name=name;
values=new int[1024];
}
}
public static void main(String[] args) {
int count=100;//對象數量改成100,保證堆內存不會溢出
WeakReference[] values=new WeakReference[count];
for(int i=0;i<count;i++){
values[i]=new WeakReference<BiggerObject>(new BiggerObject("Object-"+i));
} 
System.out.println(((BiggerObject)(values[values.length-1].get())).name);
System.gc();//強制進行垃圾回收
for(int i=0;i<10;i++){
System.out.println(((BiggerObject)(values[i].get())).name);
} 
} 
}

即便堆內存夠用,當咱們強制進行垃圾回收時,弱引用所引用的對象仍是被垃圾收集器回收。

虛引用

一個對象是否有虛引用的存在,徹底不會對其生存時間構成影響,也沒法經過虛引用來獲取一個對象的實例。爲一個對象設置虛引用關聯的惟一目的就是能在這個對象被收集器回收時收到一個系統通知。

垃圾回收時回收,沒法經過引用取到對象值,能夠經過以下代碼實現

Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj);
obj=null;
pf.get();//永遠返回null
pf.isEnQueued();//返回是否從內存中已經刪除

虛引用是每次垃圾回收的時候都會被回收,經過虛引用的get方法永遠獲取到的數據爲null,所以也被成爲幽靈引用。虛引用主要用於檢測對象是否已經從內存中刪除。

相關文章
相關標籤/搜索