優れたJavaプログラマーは、GCの仕組み、GCのパフォーマンスを最適化する方法、およびGCとのやり取りを制限する方法を理解する必要があります。メモリ効率を管理することによってのみ、包括的に改善されます。この記事では、最初にGCの実用的な原則を簡単に紹介し、次にGCのいくつかの重要な問題に関する詳細な議論を行い、最終的にGCの観点からJavaプログラムのパフォーマンスを改善するためのJavaプログラミングの提案を提出します。
GCの基本原則
Javaのメモリ管理は、実際にはオブジェクトの割り当てとリリースを含むオブジェクトの管理です。
プログラマーの場合、オブジェクトへのすべての参照がNULLに割り当てられている限り、オブジェクトをリリースするときに新しいキーワードが使用されます。 .GCは、すべての /「到達可能 /」オブジェクトのメモリ空間を取り戻す責任があります。
GCの場合、プログラマがオブジェクトを作成すると、GCはオブジェクトのアドレス、サイズ、使用状況の監視を開始します。一般的に、GCは指示されたグラフを使用して、ヒープ(ヒープ)のすべてのオブジェクトを記録および管理します(詳細については、参照1を参照)。このようにして、どのオブジェクトが「Reachable /」であり、どのオブジェクトが /「到達可能 /」であるかは、一部のオブジェクトが「到達可能 /」であると判断します。ただし、GCをさまざまなプラットフォームで実装できるようにするために、Java仕様はGCの多くの動作を厳密に規定していません。たとえば、使用するリサイクルアルゴリズムの種類やリサイクルをいつ実行するかなど、重要な問題に関する明確な規制はありません。したがって、異なるJVM実装者は、多くの場合、実装アルゴリズムが異なることがよくあります。これはまた、Javaプログラマーの開発に不確実性をもたらします。この記事では、GCの作業に関連するいくつかの問題を検討し、Javaプログラムに対するこの不確実性のマイナスの影響を減らすよう努めています。
増分GC(増分GC)
GCは通常、1つまたはプロセスのグループによって実装されています。したがって、GCが長時間実行されると、ユーザーはJavaプログラムの一時停止を感じることができます。まだリサイクルされていない多くのオブジェクトは、まだ多くのメモリを取り上げています。したがって、GCを設計するときは、一時停止時間と回復率を比較検討する必要があります。優れたGCの実装により、ユーザーは必要な設定を定義できます。他のリアルタイムオンラインゲームは、プログラムの長期的な中断を許可できません。インクリメンタルGCは、特定のリサイクルアルゴリズムを介して長期的な割り込みを多くの小さな割り込みに分割し、それによりユーザープログラムに対するGCの影響を減らすことです。増分GCは、全体的なパフォーマンスにおいて通常のGCほど効率的ではない場合がありますが、プログラムの最大一時停止時間を短縮できます。
Sun JDKが提供するHotspot JVMは、Incremental GCのデフォルトGCメソッドをサポートできます。 Hotspot JVM Incremental GCの実装は、Train GCアルゴリズムを使用することです。その基本的なアイデアは、すべてのオブジェクトを作成と使用に応じて(階層的に)グループ化し、頻繁で非常に関連性の高い使用をキューに配置し、プログラムが調整を実行するときにグループ化を続けることです。 GCが実行されると、最初に最古のオブジェクトを常にリサイクルし、グループ全体がリサイクル可能なオブジェクトである場合、GCはグループ全体をリサイクルします。このようにして、各GC実行は、到達不能なオブジェクトの特定の割合をリサイクルして、プログラムのスムーズな動作を確保します。
ファイナライズ関数の詳細な説明
Finalizeは、オブジェクトクラスにあるメソッドです。ファイナライズ関数はチェーンコールを自動的に実装していないため、それらを手動で実装する必要があるため、ファイナライズ関数の最後のステートメントは通常super.finalize()です。このようにして、下から上にファイナライズを実装するためのコールを実装できます。つまり、最初に独自のリソースをリリースしてから、親クラスのリソースをリリースできます。
Java言語仕様によれば、JVMは、このオブジェクトがファイナライズ関数を呼び出す前に到達不可能であることを保証しますが、JVMはこの関数が呼び出されることを保証しません。さらに、仕様により、ファイナライズ関数がせいぜい1回実行されることも保証されます。
多くのJava初心者は、この方法はC ++のDestructorに似ていると考えるでしょう、そして、この関数に多くのオブジェクトとリソースのリリースを配置します。実際、これは良い方法ではありません。最初に3つの理由があります。最終機能をサポートするには、GCはこの関数をカバーするオブジェクトに多くの追加作業を行う必要があります。第二に、ファイナライズの実行が完了した後、オブジェクトに到達可能になる可能性があり、GCはオブジェクトに到達可能かどうかを再度確認する必要があります。したがって、ファイナライズを使用すると、GCのパフォーマンスが低下します。第三に、GCコールがファイナライズが不確実である時期以来、この方法でリソースをリリースすることも不確かです。
一般に、ファイナライズは、一部のI/O操作やデータ接続など、制御が容易ではなく、非常に重要なリソースをリリースするために使用されます。これらのリソースのリリースは、アプリケーション全体にとって非常に重要です。この場合、プログラマーは主にプログラム自体(リリースを含む)を通じてこれらのリソースを管理し、リソースのリリースのみに依存するのではなく、デュアル保険管理メカニズムを形成するためのサプリメントとしてファイナライズ関数でリソースをリリースする方法を補完する必要があります。
ファイナライズ関数が呼び出された後、オブジェクトの最終を1回しか実行できないことを説明できることを示します。
class myobject {test main; //パブリックMyobject(テストt)でアクセシビリティを復元するために使用される{main.ref = this;// /このオブジェクトを復元して、このオブジェクトがsystem.out.printlnに到達できるように(/"これはfinalize/"); args){test = new test.ref = ref = null; .ref!= null)system.out.println(/"私のオブジェクトはまだ生きています/")};
実行結果:
これは最終化されます
Myobjectはまだ生きています
この例では、Myobjectオブジェクトはファイナライズで到達可能なオブジェクトになりますが、次にリサイクルされると、ファイナライズ関数がせいぜい1回のみ呼び出されるため、ファイナライズは呼び出されなくなります。
プログラムがGCとどのように相互作用するか
Java2は、メモリ管理関数を強化し、3つの参照クラスを定義するJava.lang.refパッケージを追加します。これらの3つの参照クラスは、これらの参照クラスを使用することにより、GCの効率を改善するために、GCと相互作用することができます。これらの参照クラスの参照強度は、到達可能なオブジェクトと到達不可能なオブジェクトの間にあります。
また、参照オブジェクトを作成することもできます。最初にオブジェクトを作成し、到達可能なオブジェクトを作成しますこの方法では、nullに通常の参照を設定します。同時に、このオブジェクトをソフト参照オブジェクトと呼びます。
ソフトリファレンスの主な特徴は、強い引用機能があることです。このタイプのメモリは、メモリが不十分な場合にのみリサイクルされるため、十分なメモリがある場合、通常はリサイクルされません。さらに、これらの参照オブジェクトは、Javaが使用されているいくつかのキャッシュを実装し、キャッシュの機能を実装し、OutFmemoryを引き起こすことなくメモリの最大限の使用を行う前に、nullに設定できます以下は、この参照タイプに次の使用擬似コードを使用します。
//画像オブジェクト画像= new Image(); //画像オブジェクトの作成... =新しいsoftreference(画像); Image = new Sreference();
弱い参照オブジェクトとソフト参照オブジェクトの最大の違いは、GCがリサイクルするときにアルゴリズムを使用してソフト参照オブジェクトがリサイクルされているかどうかを確認する必要があることです。一方、GCは常に弱い参照オブジェクトをリサイクルします。弱い参照オブジェクトは、GCによってリサイクルされる方が簡単で速いです。 GCは実行時に弱いオブジェクトをリサイクルする必要がありますが、複雑な関係を持つ弱いオブジェクトのグループは、多くの場合、完了するためにいくつかのGCの実行が必要です。弱い参照オブジェクトは、多くの場合、オブジェクトの強力な参照がnullである場合、オブジェクトを参照するためにマップ構造で使用されます。
ファントム参照はあまり有用ではなく、主にファイナライズ関数の使用を支援するために使用されます。 Phantomオブジェクトは、ファイナライズ関数を完了し、到達不可能なオブジェクトであるいくつかのオブジェクトを指しますが、GCによってリサイクルされていません。この種のオブジェクトは、後のリサイクル作業を最終化するのを支援します。
いくつかのJavaコーディングの提案
GCの実用的な原則によれば、いくつかのスキルと方法を使用して、GCをアプリケーションの要件に合わせてより効率的かつより沿って実行することができます。プログラミングに関するいくつかの提案を次に示します。
1.最も基本的な提案は、役に立たないオブジェクトの参照をできるだけ早くリリースすることです。ほとんどのプログラマーは、一時的な変数を使用する場合、アクティブなドメイン(スコープ)を終了した後、参照変数をnullに自動的に設定します。グラフなど、これらのオブジェクト間に複雑な関係があります。このようなオブジェクトの場合、GCは一般に効率が低くなります。プログラムが許可されている場合は、未使用の参照オブジェクトをできるだけ早くnullに割り当てます。 [ページ]
2。ファイナライズ関数をできるだけ少なく使用してみてください。ファイナライズ関数は、Javaがプログラマーにオブジェクトやリソースをリリースする機会を提供する機会です。ただし、GCのワークロードが増加するため、リソースをリサイクルするために、できる限り少ないファイナライズを使用してみてください。
3.頻繁に使用する写真を使用する必要がある場合は、ソフトアプリケーションタイプを使用できます。 AutOfMemoryを引き起こすことなく、プログラムを可能な限りメモリに保存できます。
4.配列、ツリー、グラフ、リンクされたリストなどのデータ構造を含む収集データ型に注意してください。また、いくつかのグローバル変数といくつかの静的変数に注意してください。これらの変数は、ぶら下がっている参照を簡単に引き起こし、メモリ廃棄物を引き起こす傾向があります。
5.プログラムに一定の待機時間がある場合、プログラマーはSystem.gc()を手動で実行してGCを実行するように通知できますが、Java言語仕様はGCが実行されることを保証しません。増分GCを使用すると、Javaプログラムの一時停止時間を短縮できます。