インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか?アリP8アーキテクトは、詳細な分析あなたを取ります!

強い参照、ソフト参照、弱参照、ファントム参照:参照型の4種類の合計でJava(実際には、そのようなFinalReferenceのようないくつかの他の参照タイプがあります)。

ここで私たちは、多くの場合、オブジェクトA =新しいオブジェクト()を使用することを強い参照;参照を対応するJavaクラスでは、このフォームではなく。

この記事では、柔らかい、弱い、見積もりを分析することである仮想基準を実装し、3つの参照型は参照クラス、メインロジックもリファレンスから継承されます。

問題

分析の前に、いくつかの質問を投げる前に?

1.ソフト参照を紹介するオンライン記事の大半は、次のとおりです。メモリ不足をどのように定義されていることを、時間のメモリにリサイクルされますか?メモリ不足によって何を意味していますか?

役に立たない、ぶら下がり参照は、オブジェクトのライフサイクルを決定するものではありません。2.ファントム参照を紹介するオンライン記事のほとんどがあります。主に、ガベージコレクタ活性回収オブジェクトを追跡するために使用されます。それは本当にですか?

3.ファントム参照は、その下には、中にJDK内のシーンを使用していましたか?

参照

我々はいくつかの分野でReference.javaを見て

public abstract class Reference<T> {
   //引用的对象
   private T referent;        
   //回收队列,由使用者在Reference的构造函数中指定
   volatile ReferenceQueue<? super T> queue;
    //当该引用被加入到queue中的时候,该字段被设置为queue中的下一个元素,以形成链表结构
   volatile Reference next;
   //在GC时,JVM底层会维护一个叫DiscoveredList的链表,存放的是Reference对象,discovered字段指向的就是链表中的下一个元素,由JVM设置
   transient private Reference<T> discovered;  
   //进行线程同步的锁对象
   static private class Lock { }
   private static Lock lock = new Lock();
   //等待加入queue的Reference对象,在GC时由JVM设置,会有一个java层的线程(ReferenceHandler)源源不断的从pending中提取元素加入到queue
   private static Reference<Object> pending = null;

ライフサイクルの参照オブジェクトを次のように

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


これは、2つの部品Javaネイティブ層と層に分割しました。

ネイティブGC層は、参照オブジェクト(コードreferenceProcessor.cppのprocess_discovered_references法)でDiscoveredList回収に追加する必要があり、その後PendingList(コードreferenceProcessor.cpp enqueue_discovered_ref_helper法)、チームPendingListに素子DiscoveredListを移動しますリファレンスは、保留中のオブジェクトの最初のクラスです。

Javaのコード層を見てください

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


プロセスは比較的簡単です:要素アウトPendingListの安定した流れから抽出し、それがReferenceQueueを行くために追加され、開発者が回復し、イベント対象に世論調査のReferenceQueue要素から認識することができます。

また、(ファントム参照から継承)クリーナータイプのオブジェクトが追加の処理を持っていることに注意:これは回収されたオブジェクトを指す場合、それは、主に対応するリサイクルするために使用される清浄なメソッドを呼び出しますヒープ内の外部メモリは、Java仮想基準で、典型的なアプリケーションであるクリーナーとDirectByteBufferヒープメモリの外部に回収されます。

リファレンスの実現を読んだ後、その後、異なるそれぞれ有するいくつかの達成クラス、見てください。

SoftReference

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


ソフト参照を実現するより、二つのフィールド非常に簡単です:クロックとタイムスタンプ。クロックは静的変数で、フィールドは、現在の時刻に毎回GCに設定されます。(回収されていないターゲットに等しくない場合)、タイムスタンプフィールドは、クロックとそれに割り当てられた各メソッドの呼び出しで取得します。

これら2つのフィールドは、それがあることを役割とは何ですか?それは何を問題ではない場合、それは唯一のソフト参照し、メモリ不足で回収されたのですか?

オブジェクトは回復がGCで実装されているかどうかを決定する必要があるため、JVMは、ジョブのソースコードを参照してくださいする必要があります。

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


特定の参照型に格納されているrefs_lists process_discovered_reflist方法を作用するオブジェクトを削除することで、このGC(ファントム参照、ソフト、弱、参照、等)に見出さオフrefs_listsから回収する必要はない、refs_lists最後の残りの要素すべての要素が回収される必要があり、場所は、最初の要素は、上記Reference.java位ペンディングフィールドに割り当てられています。

NeverClearPolicy、AlwaysClearPolicy、LRUCurrentHeapPolicy、LRUMaxHeapPolicy:4種類の合計を達成ReferencePolicy。

SoftReferenceを回復したことがない代表は、JVMクラスでは使用されません常にfalseを返しますNeverClearPolicyは、AlwaysClearPolicyは、それが使用されますAlwaysClearPolicyのように、AlwaysClearPolicyのポリシーセットすることができreferenceProcessor.hpp#セットアッププロセスでは、trueを返すことはありません私たちは自分で勉強することができます興味を持っています。

LRUCurrentHeapPolicy和LRUMaxHeapPolicy的should_clear_reference方法则是完全相同:

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


timestamp_clock就是SoftReference的静态字段clock,java_lang_ref_SoftReference::timestamp(p)对应是字段timestamp。如果上次GC后有调用SoftReference#get,interval值为0,否则为若干次GC之间的时间差。

_max_interval则代表了一个临界值,它的值在LRUCurrentHeapPolicy和LRUMaxHeapPolicy两种策略中有差异

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


其中SoftRefLRUPolicyMSPerMB默认为1000,前者的计算方法和上次GC后可用堆大小有关,后者计算方法和(堆大小-上次gc时堆使用大小)有关。

看到这里你就知道SoftReference到底什么时候被被回收了,它和使用的策略(默认应该是LRUCurrentHeapPolicy),堆可用大小,该SoftReference上一次调用get方法的时间都有关系。

WeakReference

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


可以看到WeakReference在Java层只是继承了Reference,没有做任何的改动。那referent字段是什么时候被置为null的呢?要搞清楚这个问题我们再看下上文提到过的process_discovered_reflist方法:

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


不管是弱引用还是其他引用类型,将字段referent置null的操作都发生在process_phase3中,而具体行为是由clear_referent的值决定的。而clear_referent的值则和引用类型相关。

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


可以看到,对于Soft references和Weak references clear_referent字段传入的都是true,这也符合我们的预期:对象不可达后,引用字段就会被置为null,然后对象就会被回收(对于软引用来说,如果内存足够的话,在Phase 1,相关的引用就会从refs_list中被移除,到Phase 3时refs_list为空集合)。

但对于Final references和 Phantom references,clear_referent字段传入的是false,也就意味着被这两种引用类型引用的对象,如果没有其他额外处理,只要Reference对象还存活,那引用的对象是不会被回收的。Final references和对象是否重写了finalize方法有关,不在本文分析范围之内,我们接下来看看Phantom references。

PhantomReference

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


可以看到虚引用的get方法永远返回null,我们看个demo。

インタビューでは、多くの場合、Javaの参照型原理について尋ねましたか? アリP8アーキテクトは、詳細な分析あなたを取ります!


从以上代码中可以看到,虚引用能够在指向对象不可达时得到一个'通知'(其实所有继承References的类都有这个功能),需要注意的是GC完成后,phanRef.referent依然指向之前创建Object,也就是说Object对象一直没被回收!

而造成这一现象的原因在上一小节末尾已经说了:对于Final references和 Phantom references,clear_referent字段传入的时false,也就意味着被这两种引用类型引用的对象,如果没有其他额外处理,在GC中是不会被回收的。

对于虚引用来说,从refQueue.remove();得到引用对象后,可以调用clear方法强行解除引用和对象之间的关系,使得对象下次可以GC时可以被回收掉。

End

针对文章开头提出的几个问题,看完分析,我们已经能给出回答:

私たちはしばしば、オンラインソフト参照のプレゼンテーションを参照してください。1.次のとおりです。メモリ不足をどのように定義されていることを、時間の記憶の回復だろうか?なぜそれがメモリ不足と呼ばれていますか?

ソフト参照は、低メモリ、メモリ不足と基準オブジェクトの定義を回収し、使用可能なヒープメモリサイズを取得する現在時刻が関係を有する、計算式は、上記説明しました。

仮想基準のオンラインプレゼンテーション2.は、以下のとおりです。非存在、および他のいくつかの参考文献は、仮想基準のライフサイクル異なっており、オブジェクトを決定するものではありません。主に、ガベージコレクタ活性回収オブジェクトを追跡するために使用されます。それは本当にですか?

何の治療は、限り、ファントム参照が回収されないよう、そして、それがオブジェクトが回収されることはありません参照していない場合は厳密に言えば、ファントム参照は、オブジェクトのライフサイクルに影響を与えます。PhantomReferenceオブジェクトが(他のGC ROOT到達可能なオブジェクトによって参照されるように)、その後、回復しないのであれば、一般的には、ReferenceQueueからPhantomReferenceオブジェクトを取得した後、あなたはリフトPhantomReferenceとオブジェクトの参照関係への参照に明確な道を呼び出す必要があります。

3.ファントム参照は、その下には、中にJDK内のシーンを使用していましたか?

DirectByteBufferは、外部ヒープメモリの回復を実装するためにファントム参照サブクラスCleaner.javaで、フォローアップがために記事を書きますインとアウト外メモリヒープと述べました。

記事はそれに弟の注目のポイントに古き良き鉄を感じます!


おすすめ

転載: blog.51cto.com/14480698/2479280