Javaのガベージコレクション - 到達可能性解析アルゴリズム

https://www.cnblogs.com/jxldjsn/p/11127897.html

Javaで来て、参照することによって関連付けられたオブジェクトは、それはあなたがオブジェクトを操作したい場合は、参照することによって行われなければならないと言うことです。だから、簡単な方法は、オブジェクトが再利用できるかどうかを判断するために参照カウントを通じてであることは明らかです。一般性を失うことなく、オブジェクトは、それに関連付けられた参照を持たない場合、それは基本的なオブジェクトが他の場所で使用されにくいことを示し、そのオブジェクトは、オブジェクトを再利用することができるとなります。このように、参照カウントとなります。

この手法の特徴は、(Pythonの参照カウントが使用される)単純であり、高効率、それは循環参照の問題を解決しない、Javaおよび従って、このような方法で使用されていません。次のコードを見てください:

  1. パブリック  クラス  メイン{
  2.   パブリック  静的  ボイド  メイン(文字列[]引数){
  3.  MyObjectにオブジェクト1 =  新しいMyObjectに();
  4.  MyObjectにオブジェクト2 =  新しいMyObjectに();
  5.  
  6.  object1.object = object2は、
  7.  object2.object =オブジェクト1。
  8.   
  9.  オブジェクト1 =  NULL;
  10.  オブジェクト2 =  NULL;
  11.  }
  12.  }
  13.   
  14.   クラス  MyObjectに{
  15.   公共Objectオブジェクト=  NULL;
  16.  }

最後の二つの物体1直面するとオブジェクト2の割り当てがヌルである、すなわち、物体1とオブジェクト2点がもはやアクセスできない対象であったと言うことであるが、それらはお互いを参照するため、それらをカウントは、その後、ガベージコレクタ0である基準ないせる彼らは回復しません。


この問題を解決するには、Javaで到達可能性解析手法を取ります。この方法の基本的な考え方は、「GCのルーツ」と対象物との間には到達可能なルートが存在しない場合、オブジェクトが呼び出されていないが、それはことに留意すべきである、検索のための出発点として、「GCのルーツ」オブジェクトの一連行われますこれは、ターゲットは、必ずしも到達不能リサイクル対象となりませんことを決定しました。プロセスがリサイクル対象となり脱出まだない場合には、少なくとも二回これら2つのマークの可能性をラベリング処理を受けなければならない、あなたは基本的には本当にリサイクルの対象となるオブジェクトをリサイクルするための到達不能オブジェクトであると判断しています。最後の二つの物体1直面するとオブジェクト2の割り当てがヌルである、すなわち、物体1とオブジェクト2点がもはやアクセスできない対象であったと言うことであるが、それらはお互いを参照するため、それらをカウントは、その後、ガベージコレクタ0である基準ないせる彼らは回復しません。

「到達可能性分析は、」生きているオブジェクトは(また、この方法だけでなく、C位、Lisp-最も早い動的メモリ割り当てを使用するかどうかを決定するためながらJavaは、オブジェクトが「デッド」されているかどうかを決定するために参照カウント法を使用していません言語)。 
このアルゴリズムの核となるアイデア:オブジェクトの一連のこれらのノードから下に検索を開始するために、出発点として、「GCのルーツ」と呼ばれるが、サーチパスは、「参照の連鎖」は、任意のせずにGCルーツにオブジェクトとして知られている横断しますチェーンは、オブジェクトが使用できないことを示し、(GCルーツから到達不能このオブジェクトへの)基準時間に接続されている場合。例として、次の図: 

°è¿éåå¾çæè¿

まだオブジェクトObject5 -Object7の間で相互に接触にいる間、彼らはGCのルーツまでではありませんので、彼らはリサイクル可能なオブジェクトであることが決定されます。

Java言語では、オブジェクトのGCのルーツとして使用することができ、以下は含まれています。

  1. オブジェクト参照での仮想マシンのスタック(ローカル変数表のスタックフレーム)。(ローカル変数テーブルであるスタックフレーム内のオブジェクトへのすべての言及として理解することができます)
  2. 静的属性参照におけるオブジェクトのメソッド(と理解することができる:静的プロパティのすべてのオブジェクトの参照方法の領域)
  3. (理解されるように:参照方法の定常領域のすべてのオブジェクト)参照定数のオブジェクトのメソッド
  4. ネイティブメソッドスタックオブジェクト(以下のように理解することができる:すべてのオブジェクトがネイティブメソッドを参照)(ネイティブメソッド)参照

それは次のように理解することができます。

(1)まず、仮想マシン・スタックの最初のオブジェクト参照で、私たちは通常の手順でオブジェクトを作成し、オブジェクトは、ヒープ上のスペースを開き、仮想マシンのスタックを保存するために基準空間としてこの問題に対処しますオブジェクトのライフサイクルが終わったならば、それは仮想マシンのスタックスタックから参照されるので、仮想マシン・スタック内の参照がある場合、それは対象が有用であることを意味し、これが最も一般的です。

仮想マシンスレッドのスタックがプライベートであるため、そのようなオブジェクトへの参照は、共有アプローチエリアに格納されるため、(2)第二に、我々は、クラス内のグローバル静的オブジェクトを定義すること、すなわち、静的キーワードの使用であります明らかGCルーツなどの静的基準領域の方法が不可欠です。

(3)第三に、この基準の後に初期化が改変されていないため、一定の基準は、キーワードのstatic finalを使用することであるので、一定のプールエリアのオブジェクトメソッドの参照は、GCのルーツとして考慮されるべきです。最後の1は、JNI技術を使用している、時には純粋なJavaコードは、当社のニーズを満たしていない、我々はCやC ++、Javaのコード、およびネイティブメソッドのため、使用、JVMのメモリを呼び出す必要があり、特別なローカル方法がありますオブジェクトネイティブメソッドスタックがGCルーツとして参照されるように、これらのオブジェクトへの参照を保存するスタック。

JVMは、被験者の生存(参照カウントアルゴリズム、到達可能性分析アルゴリズム、最終決定)か否かを判断します

最終目的は、生きているかどうかを判断する()メソッドを終了:

    でも到達可能性解析アルゴリズムのオブジェクトで到達でき、そしてそれは「Feisibuke」ではない、と彼らは、「保護観察」段階に一時的にしているこの時間は本当に、少なくとも再びマークプロセスを通過するために、オブジェクトの死を宣言します。
    提供されるターゲットマークが行われたストランド到達可能性分析は、接続されたGCのルーツへの参照が見つかりませんでした。
  1)第一マーカーおよびスクリーニング。
    スクリーニング条件は、このオブジェクトがファイナライズ()メソッドを実行する必要があるかどうかです。
    オブジェクトがfinalizeメソッドを覆われていない、またはfinzlize方法は、仮想マシン上で呼び出された場合には、これらの2つの場合は、「実行する必要はない」と考えられている仮想マシンは、オブジェクトが回収されます。

  2)第2のマーカー
    の目的は、ファイナライズ()メソッドを実行するために必要であると判断された場合、オブジェクトが名前のファイルに配置されます。後で仮想マシンによって自動的にキューのうち、F-キュー、および実行する優先度の低いファイナライザスレッドを設立しました。ここで、「実行」という用語は、このメソッドをトリガーする仮想マシンを意味し、それは、それは実行の終了を待つことになる約束しません。この理由は、オブジェクトのファイナライズ()スローを実行するための方法、または無限ループ(より極端な場合)が発生した場合、それは待ち状態に恒久的に他のオブジェクトF-キューのキューを引き起こし、さらには全体のメモリを引き起こす可能性があることです回収システムがクラッシュします。
    ファイナライズ()メソッドは、オブジェクトが、死の運命を脱出する最後のチャンスである、GC意志第2小マークの後のF-キューオブジェクト、オブジェクトが再限り)(ファイナライズで彼の成功を保存する場合-----クラスまたはオブジェクト変数に自分自身を割り当て、そして、第2のマークの「回復する」を削除することをするためにそのようなメンバ変数の集合として、チェーン上のオブジェクトの任意の会合を指すことができます。オブジェクトは、この時間をエスケープしていない場合、それは本当に基本的に回復していることです。
このフローチャートは以下のようです:

在JDK1.2以前,Java中引用的定义很传统: 如果引用类型的数据中存储的数值代表的是另一块内存的起始地址,就称这块内存代表着一个引用。这种定义有些狭隘,一个对象在这种定义下只有被引用或者没有被引用两种状态。 
我们希望能描述这一类对象: 当内存空间还足够时,则能保存在内存中;如果内存空间在进行垃圾回收后还是非常紧张,则可以抛弃这些对象。很多系统中的缓存对象都符合这样的场景。 
在JDK1.2之后,Java对引用的概念做了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)四种,这四种引用的强度依次递减。

⑴强引用(StrongReference)
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。  ps:强引用其实也就是我们平时A a = new A()这个意思。

⑵软引用(SoftReference)
如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存(下文给出示例)。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

⑶弱引用(WeakReference)
弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

⑷虚引用(PhantomReference)
“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
主にオブジェクトを追跡するために使用されるファントム参照は、ガベージコレクタ活性を回復しました。仮想基準および基準を組み合わせて使用​​(ReferenceQueue)をキューイングしなければいけません:ソフトと弱参照との間の仮想基準差を参照していることです。ガベージコレクタは、オブジェクトの準備ができて回復がある場合には、仮想的な基準がある場合は、メモリの前に、この参照が参照に関連付けられた仮想キューに追加されて回収されることが分かりました。

図1は、なぜ我々はソフト参照を使用する必要がない

のは、従業員情報照会システムの例を見てみましょう、まず。私たちは、ディスク・ファイルやデータベースに格納されている情報の従業員情報照会システムのクエリ言語のJavaの従業員の人事ファイルを使用します。ユーザーとしては、完全に可能私たちは数分、あるいは秒前に見られていた従業員のファイル情報を見に戻って行く必要がある(同様に、私たちはしばしば、ブラウザWEBページに「戻る」ボタンを使用します)。

その後、我々は通常、2つのプログラムの実装を持っています:

一つは、次のとおりです。

過去には、メモリに保存されている従業員情報、Javaは常にアプリケーション全体で従業員のプロファイル情報をオブジェクトの各ストレージライフサイクルを見ました。

その他は以下のとおりです。

ユーザーは、現在、Javaオブジェクト閲覧店従業員のファイル情報は、ユーザーが再び従業員のファイルを参照する必要があるとき、彼らは占有メモリ領域を再利用できるよう、ガベージコレクションスレッドの終了を参照するときに、他の従業員のファイル情報を表示して起動すると時間情報、従業員を再構築するための情報。

もちろん、最初の実装は、無駄なメモリを大量に発生します。

第二の欠陥は、オブジェクトがガベージコレクションのスレッドのガベージコレクションされていない場合でも達成され、まだよくメモリに保存されている従業員のプロファイル情報が含まれている、オブジェクトを再構築しなければならないアプリケーション。

我々は、彼らがまだ参照を回復していないJavaオブジェクトを取得することができれば、このようなデータベースのクエリ操作としてディスクファイルへのアクセス、アクセスネットワークリソースは、アプリケーションの実行性能に影響を与える重要な要因であることを、大幅に改善し、不要な訪問を減らすことを知っていますプログラムの実行速度が向上。

おすすめ

転載: www.cnblogs.com/ldddd/p/11321104.html