前書き
javaガベージコレクションメカニズムは、オブジェクトが再利用されるかどうかを判断するために、参照カウント方法と到達可能性分析アルゴリズムの2つの方法を使用します。
jdk1.2以前は、1種類の参照しかありませんでした。オブジェクトが参照されると存在します。参照がない場合、参照数は0であり、ガベージコレクションによってオブジェクトは無効と判断されます。
Javaはjdk1.2から始まりました。オブジェクト参照には、強い参照>ソフト参照>弱い参照>仮想参照の4種類があります。プログラマーは、さまざまな参照を通じてオブジェクトのライフサイクルを制御して、ガベージコレクションを容易にし、プログラムをより柔軟にすることができます。オブジェクトのライフサイクルを制御する
Javaはjdk1.2で始まり、java.lang.refに抽象クラスReferenceと3つの実装クラスSoftReference(ソフトリファレンス)、WeakReference(ウィークリファレンス)、PhantomReference(仮想リファレンス)を提供しました。
強い引用
/**
* 强引用
*/
public void testStrongReference(){
//强引用
Object obj=new Object();
}
ビジネスコード内のほとんどのオブジェクトは、Object obj = new Object()などの強力な参照です。このような参照オブジェクトは、ガベージコレクションされることはありません。オブジェクトを作成するためのメモリを割り当てるのに十分なメモリがない場合、Java仮想マシンはスローします。 OOMエラーが発生すると、プログラムが異常終了し、このオブジェクトはリサイクルされません。参照が消えた後(*明示的にnullに割り当てられた*、メソッドのライフサイクルが終了したなど)にのみ、参照カウントは0になり、ガベージが収集されます。
ソフトリファレンス
/**
* 软引用
*/
public void testSoftReference(){
//强引用
Object obj=new Object();
//放入SoftReference
SoftReference<Object> softReference = new SoftReference<Object>(obj);
System.out.println( softReference.get());//java.lang.Object@39a054a5
}
ソフトリファレンスは、ストロングリファレンスよりも1レベル低く、有用で必須ではないオブジェクトを表すために使用されます。メモリが不足している場合にのみ、ソフトリファレンスオブジェクトはガベージコレクションされ、メモリオーバーフローを心配せずにキャッシュを実現できます。
/**
* 软引用(引用队列)
*/
public void testSoftReferenceQueue(){
//引用队列
ReferenceQueue referenceQueue = new ReferenceQueue<>();
//使用守护线程
Thread thread= new Thread(new Runnable() {
@Override
public void run() {
try {
int i=0;
SoftReference<Integer> softReference;
//如果对象被gc回收
while((softReference = (SoftReference) referenceQueue.remove()) != null) {
System.out.println("第"+i+"次回收:"+softReference);
i++;
}
}catch (Exception e){
}
}
});
thread.setDaemon(true);//设置为守护线程,监听对象变化
thread.start();
Map<Object, Object> map = new HashMap<>();
Object obj=new Object();
for(int i=0;i<2000; i++){
//放入SoftReference转为软引用
byte [] bytes=new byte[1024*1024];
SoftReference<byte []> softReference = new SoftReference<byte []>(bytes,referenceQueue);
//将软引用作为key
map.put(softReference,obj);
}
}
第1992年収:java.lang.ref.SoftReference@7c7a06ec
第1993年収:java.lang.ref.SoftReference@1d296da
第1994年収:java.lang.ref.SoftReference@776aec5c
[GC(割り当て失敗)[PSYoungGen :30K-> 64K(1536K)] 3833K-> 3866K(5632K)、0.0002270秒] [時間:user = 0.00 sys = 0.00、real = 0.00秒]
[GC(割り当ての失敗)[PSYoungGen:64K-> 64K(1536K )] 3866K-> 3866K(5632K)、0.0002042秒] [時間:user = 0.00 sys = 0.00、real = 0.00秒]
[フルGC(割り当てエラー)[PSYoungGen:64K-> 0K(1536K)] [ParOldGen:3802K -> 3802K(4096K)] 3866K-> 3802K(5632K)、[メタスペース:3120K-> 3120K(1056768K)]、0.0019695秒] [時間:ユーザー= 0.00sys = 0.00、実数= 0.00秒]
[GC(割り当ての失敗)[PSYoungGen:0K-> 0K(1536K)] 3802K-> 3802K(5632K)、0.0002220秒] [時間:user = 0.00 sys = 0.00、real = 0.00秒]
[完全なGC(割り当ての失敗)[PSYoungGen:0K-> 0K(1536K)] [ParOldGen:3802K-> 730K(4096K)] 3802K-> 730K(5632K)、[メタスペース:3120K-> 3120K(1056768K)]、0.0025588秒] [時間:user = 0.00 sys = 0.00、real = 0.00秒]
1995年の回復:java.lang.ref.SoftReference@408d971b
1996年の回復:java.lang.ref.SoftReference@75d4a5c2
1997年の回復: java.lang.ref.SoftReference@557caf28
ソフトリファレンスはSoftReferenceによって実装されます。ソフトリファレンスオブジェクトはリファレンスキュー(Referencequeue)に登録でき、リファレンスキューはオブジェクトが解放されたかどうかを判断するために使用されます。リファレンスには次のフィールドがあります。状態に応じて判断できる状態は4つありますが、次はそれをキューに入れることは理にかなっています(エンキューするときだけ、nextは処理される次のReferenceオブジェクトに設定されるため)
active:メモリが割り当てられたときの状態。
保留中:メモリが再利用され、関連付けられた参照キューに格納されようとしている状態。
エンキュー:メモリが再利用されると、参照キューの状態になります。
非アクティブ:非アクティブ状態。
弱い参照
/**
* 弱引用
*/
public void testWeakReference(){
//强引用
Object obj=new Object();
//放入WeakReference
WeakReference<Object> weakReference = new WeakReference<Object>(obj);
System.out.println(weakReference.get());//java.lang.Object@39a054a5
}
弱い参照は、ソフト参照よりも最初のレベルです。これらは、必須ではないオブジェクトを表すために使用されます。メモリが十分であるかどうかに関係なく、オブジェクトはガベージ収集されます。ただし、ガベージ収集スレッドの優先度が非常に低いため、
弱い参照はWeakReferenceを介して迅速に収集されません。実装のために、弱い参照オブジェクトを参照キュー(Referencequeue)に登録し、参照キューを使用してオブジェクトが解放されたかどうかを判別できます。テストしたい場合は、上記で弱く参照されているスレッド監視方法を使用できます
ファントムリファレンス
/**
* 虚引用
*/
public void testPhantomReference(){
//强引用
Object obj=new Object();
//必须使用引用队列
ReferenceQueue referenceQueue = new ReferenceQueue();
//放入PhantomReference
PhantomReference<Object> phantomReference = new PhantomReference<Object>(obj,referenceQueue);
System.out.println(phantomReference.get());//null 因为虚引用无法获取对象实例,只是监听作用
System.out.println(obj);//java.lang.Object@39a054a5
}
仮想参照
他の参照と比較すると、仮想参照があると同じように仮想参照。オブジェクトのインスタンスは、仮想参照を介して入手することができません。オブジェクトは唯一の仮想参照によって保持されている場合、それはいつでもガベージコレクトになります。ソフト参照および弱参照とは異なり、それは必要がありますReferencequeueに登録され、オブジェクトがリサイクルされようとしているときに、仮想参照を参照キューに入れ、仮想参照が参照キューに追加されているかどうかを判断して、オブジェクトをリサイクルする必要があるかどうかを判断します。