ホームページ  >  記事  >  Java  >  Java での参照の使用法について

Java での参照の使用法について

黄舟
黄舟オリジナル
2017-03-16 10:19:072084ブラウズ

この記事は主に 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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。