この記事は主に Java での Reference の使い方の詳細な説明に関する関連情報を紹介します。必要な方は参考にしてください
Java Reference 詳細
jdk 1.2 以降では、強い リファレンス 、ソフト リファレンス 、弱いリファレンス 。これら 4 つの概念への仮想参照である参照が導入されています。これら 4 つの概念についてはインターネット上に多くの説明がありますが、今日はコードに基づいて分析したものがほとんどです (参照型は Java パッケージ内にあります)。 lang.ref 内)。
1. 強参照(StrongReference)
強参照はGCによってリサイクルされず、java.lang.refには実際に対応する型がありません。例:
Object obj = new Object();
ここでの obj 参照は強参照であり、GC によってリサイクルされません。
2. ソフト参照 (SoftReference)
ソフト参照は、JVM がメモリ不足を報告すると GC によってリサイクルされ、そうでない場合はリサイクルされません。プールすること。ソフト参照の使用法:
Object obj = new Object(); SoftReference<Object> softRef = new SoftReference(obj); // 使用 softRef.get() 获取软引用所引用的对象 Object objg = softRef.get();
3. 弱参照(WeakReference)
GCは弱参照オブジェクトを発見すると、WeakReferenceで参照されているオブジェクトを解放します。弱い参照の使用法はソフト参照の使用法と似ていますが、リサイクル戦略が異なります。
4. Phantom Reference (PhantomReference)
GCは仮想参照オブジェクトを発見すると、PhantomReferenceオブジェクトをReferenceQueueキューに挿入します。このとき、PhantomReferenceが指すオブジェクトはGCによってリサイクルされません。ただし、ReferenceQueue が実際に処理されるまでリサイクルされません。仮想参照の使い方:
Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue); // 调用phanRef.get()不管在什么情况下会一直返回null Object objg = phanRef.get(); // 如果obj被置为null,当GC发现了虚引用,GC会将phanRef插入进我们之前创建时传入的refQueue队列 // 注意,此时phanRef所引用的obj对象,并没有被GC回收,在我们显式地调用refQueue.poll返回phanRef之后 // 当GC第二次发现虚引用,而此时JVM将phanRef插入到refQueue会插入失败,此时GC才会对obj进行回收 Reference<? extends Object> phanRefP = refQueue.poll();
簡単な定義を読んだ後、強参照は言うまでもなく、ソフト参照の説明も非常に明確です。 「仮想参照」引用」。
弱参照:
public static void main(String[] args) throws InterruptedException { Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); WeakReference<Object> weakRef = new WeakReference<Object>(obj, refQueue); System.out.println(weakRef.get()); System.out.println(refQueue.poll()); obj = null; System.gc(); System.out.println(weakRef.get()); System.out.println(refQueue.poll()); }
System.gc() は JVM に GC を実行するのに良い時期であることを伝えますが、具体的に実行するかどうかは JVM によって決定されるため、JVM がGC を実行し、結果が得られます。 つまり、(実際、このコードは通常 GC を実行します):
java.lang.Object@de6ced null null java.lang.ref.WeakReference@1fb8ee3
実行結果から、GC は、weakRef.get() を呼び出すことで obj オブジェクトを取得することがわかります。実行されず、refQueue.poll() 返された null は、obj = null に設定した場合、ヒープ内に obj オブジェクトへの参照がありません。ここで、JVM は、weakRef.get( を通じて GC を実行しました。 ) null が返され、refQueue.poll() が WeakReference オブジェクトを返したので、JVM は obj をリサイクルした後、refQueue キューにweakRef を挿入します。
ダミー参照:
public static void main(String[] args) throws InterruptedException { Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue); System.out.println(phanRef.get()); System.out.println(refQueue.poll()); obj = null; System.gc(); System.out.println(phanRef.get()); System.out.println(refQueue.poll()); }
同様に、JVM が GC を実行すると、結果は次のようになります:
null null null java.lang.ref.PhantomReference@1fb8ee3
実行結果から、前に述べたことが正しいことがわかります。 phanRef.get( ) は、状況に関係なく、JVM が GC を実行して仮想参照を検出すると、refQueue.poll() を呼び出すときに、対応する仮想参照キューに PhantomReference オブジェクトを挿入します。 PhantomReference オブジェクトを使用する場合、poll メソッドはまず PhantomReference の保持キュー キュー (ReferenceQueue45295be6c16aa7c869014d0501ab2b76) を NULL に設定します。NULL オブジェクトは ReferenceQueue からを継承し、enqueue(Reference paramReference) メソッドをに上書きします。 return false し、obj が GC によって再度検出されると、JVM は PhantomReference を NULL キューに挿入しますが、挿入は失敗して false を返します。このとき、GC は obj をリサイクルします。実際、このコードでは、obj がリサイクルされているかどうかを知ることはできませんが、PhantomReference の javadocコメント には次のような文があります。可能であれば、対応するキューにエンキューされていますが、その参照先は
クリアされていません。つまり、ファントム参照の参照キューは、何らかのアプリケーション コードによって明示的に処理される必要があります。シンプルなので、多くの人が理解できるはずだと思います): 「obj」が仮想的に到達可能であると GC が判断すると、そのオブジェクト (PhantomReference を参照) は対応するキューにエンキューされますが、そのポインターの世代はクリアされていません。つまり、仮想参照の参照キューは、アプリケーション コードによって明示的に処理される必要があります。
弱参照と仮想参照の使用
软引用很明显可以用来制作caching和pooling,而弱引用与虚引用呢?其实用处也很大,首先我们来看看弱引用,举个例子:
class Registry { private Set registeredObjects = new HashSet(); public void register(Object object) { registeredObjects.add( object ); } }
所有我添加进 registeredObjects 中的object永远不会被GC回收,因为这里有个强引用保存在registeredObjects里,另一方面如果我把代码改为如下:
class Registry { private Set registeredObjects = new HashSet(); public void register(Object object) { registeredObjects.add( new WeakReference(object) ); } }
现在如果GC想要回收registeredObjects中的object,便能够实现了,同样在使用HashMap如果想实现如上的效果,一种更好的实现是使用WeakHashMap。
而虚引用呢?我们先来看看javadoc的部分说明:
Phantom references are useful for implementing cleanup operations that are necessary before an object gets garbage-collected. They are sometimes more flexible than the finalize() method.
翻译一下:
虚引用在实现一个对象被回收之前必须做清理操作是很有用的。有时候,他们比finalize()方法更灵活。
很明显的,虚引用可以用来做对象被回收之前的清理工作。
以上がJava での参照の使用法についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。