Javaには、強参照、ソフト参照、弱参照、仮想参照の4種類の参照があります。
4つの主要な引用デザイン機能
Javaのメモリ割り当てとメモリ回復はすべてJVMによって処理されるためです。オブジェクトをリサイクルできるかどうかは、主に、到達可能性を分析できるこのオブジェクトへの参照があるかどうかに依存します。プログラマーは一般的にGCメソッドを積極的に呼び出さないため、オブジェクトのライフサイクルを管理する場合は、さまざまな参照を柔軟に適用してオブジェクトを作成する必要があります。
-
デザインの目的:
-
- プログラマーがコードを介してオブジェクトのライフサイクルを決定できるようにします
- ガベージコレクションを使用する
強い引用
最も広く使用されていますが、最も一般的でもあります。
Object o = new Object();
オブジェクトに強い参照が関連付けられている限り、オブジェクトがリサイクルされることはありません。メモリが不足している場合でも、JVMはOOMをスローするだけで、リサイクルはしません。
ただし、JVMでオブジェクトを再利用する場合は、強力な参照とオブジェクトの間の関連付けを解除する必要があります。
- 切断する
n=null;
確認するために、ここでは手動でGCを呼び出して、強い参照とオブジェクトの間の関連付けが中断されているかどうか、およびリソースがリサイクルされるかどうかを確認します。
public class Student {
@Override
protected void finalize()throws Throwable{
System.out.println(" Student 被回收了");
}
public static void main(String[] args) {
Student student = new Student();
System.gc();
System.out.println("===============");
student = null;
System.gc();
}
}
- 結果:
学生はリサイクルされました
-
注意
-
- 開発中にfinalizeメソッドを書き直さないでください
- 開発中に、一部のオブジェクトを手動でNULLに割り当てることができます。これにより、JVMにこれらのリソースをガベージコレクションするように通知できます。
ソフトリファレンス
- ソフトリファレンスを作成する
SoftReference<Student> studentSoftReference = new SoftReference<Student>(new Student());
- ソフトリファレンスは、オブジェクトをSoftReferenceでラップすることです。ラップされたオブジェクトをソフトリファレンスオブジェクトから取得する必要がある場合は、それを取得するだけです。
SoftReference<Student> studentSoftReference = new SoftReference<Student>(new Student());
Student student = studentSoftReference.get();
System.out.println(student);
-
特徴:
-
- メモリが不足すると、JVM GCがトリガーされます。GC後もメモリが不足している場合は、ソフトリファレンスパッケージ内のオブジェクトがリサイクルされます。
- つまり、メモリが不足している場合にのみ、JVMはオブジェクトを再利用します
-
検証:
SoftReference<byte[]> softReference = new SoftReference<byte[]>(new byte[1024*1024*10]);
System.out.println(softReference.get());
System.gc();
System.out.println(softReference.get());
byte[] bytes = new byte[1024*1024*10];
System.out.println(softReference.get());
- 実行時にJVMパラメータを追加する必要があります。-Xmx20Mは20Mの最大ヒープメモリを表します
- 結果
[B @ 452b3a41
[B @ 452b3a41
ヌル
- 手動でGCを実行した場合でも、ソフト参照オブジェクトパッケージ内のオブジェクトは問題ありません.10Mバイトを作成すると、最大ヒープメモリが不足し、ソフト参照オブジェクトはガベージコレクションされます。
- 機能:キャッシュとして使用できます。メモリが十分にある場合は、キャッシュを正常に取得できます。メモリが不足している場合は、最初にキャッシュが強制終了されるため、OOMは表示されません。
import java.lang.ref.SoftReference;
import java.util.HashMap;
/**
* SoftRefenceCache
* @param <K> key的类型.
* @param <V> value的类型.
*/
public class SoftReferenceCache<K, V> {
private final HashMap<K, SoftReference<V>> mCache;
public SoftReferenceCache() {
mCache = new HashMap<K, SoftReference<V>>();
}
/**
* 将对象放进缓存中,这个对象可以在GC发生时被回收
*
* @param key key的值.
* @param value value的值型.
*/
public void put(K key, V value) {
mCache.put(key, new SoftReference<V>(value));
}
/**
* 从缓存中获取value
*
* @param key
*
* @return 如果找到的话返回value,如果被回收或者压根儿没有就返* 回null
*/
public V get(K key) {
V value = null;
SoftReference<V> reference = mCache.get(key);
if (reference != null) {
value = reference.get();
}
return value;
}
public static void main(String[] args) {
SoftReferenceCache<Integer, String> mPersonCache = new SoftReferenceCache<Integer, String>();
mPersonCache.put(0, ("zhong"));
mPersonCache.put(1, ("hu"));
// 去拿zhong
String p = (String) mPersonCache.get(1);
}
}
弱い参照
弱参照はソフト参照に似ていますが、キーワードはWeakReferceに置き換えられます
WeakReference weakReference = new WeakReference<byte[]>(new byte[1024*1024*10]);
System.out.println(weakReference.get());
- 特徴:メモリが十分であるかどうかに関係なく、GCが発生する限りリサイクルされます(これはソフトリファレンス間の最も明らかな違いでもあります)
- 設定:ThreadLocal、WeakHashMap。
ファントムリファレンス
ファントムリファレンス
ReferenceQueue queue = new ReferenceQueue();
PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1],queue);
System.out.println(reference.get());
- ファントム参照の使用と他の使用にはまだ大きな違いがあります。
- 結果:
ヌル
- getメソッドが直接nullを返すため
- 仮想参照オブジェクトを作成するには、ラップされたオブジェクトを渡すだけでなく、ReferenceQueue(キュー)も渡します。
- ファントム参照は、ReferenceQueueと一緒に使用する必要があります。GCがオブジェクトを再利用する準備をしているときに、ファントム参照がまだあることがわかった場合、再利用される前に、関連するReferenceQueueにファントム参照が追加されます。
ReferenceQueue queue = new ReferenceQueue();
List<byte[]> bytes = new ArrayList<>();
PhantomReference<Student> reference = new PhantomReference<Student>(new Student(),queue);
new Thread(() -> {
for (int i = 0; i < 100;i++ ) {
bytes.add(new byte[1024 * 1024]);
}
}).start();
new Thread(() -> {
while (true) {
Reference poll = queue.poll();
if (poll != null) {
System.out.println("虚引用被回收了:" + poll);
}
}
}).start();
Scanner scanner = new Scanner(System.in);
scanner.hasNext();
- 結果
ファントム参照がリサイクルされました:java.lang.ref.PhantomReference @ 5ac42552
最初のスレッドはデータをコレクションに入れます。データがどんどん増えるにつれて、GCを送信する必要があります
2番目のスレッドには無限ループがあり、キューからデータを取得します。取得したデータがnullでない場合は、出力します。
GCが発生すると、ファントムリファレンスがリサイクルされ、リサイクルされた仲間がReferenceQueueに配置されます。
NIOでは、仮想参照を使用してオフヒープメモリを管理できます
やっと
- 読んでやりがいを感じたら、いいねをあげたいと思います。これが更新の最大のモチベーションになります。ご支援ありがとうございます。
- Javaとコンピュータの基本的な知識に焦点を当てた私の公開アカウント[JavaFox]に注目してください。私を信じていない場合は、私を叩いてください。
- 読んだ後に異なる意見や提案がある場合は、コメントして私たちと共有してください。皆様のご支援、ご愛顧を賜りますようお願い申し上げます。