CodeGym /Java Blog /ランダム /オブジェクトのライフサイクル
John Squirrels
レベル 41
San Francisco

オブジェクトのライフサイクル

ランダム グループに公開済み
やあ!あなたのコンピュータのメモリ量には限界があると言っても、あまり驚かないと思います :)
オブジェクトのライフサイクル - 1
ハード ドライブ (RAM の何倍ものサイズ) でさえ、お気に入りのゲーム、テレビ番組、その他のものでいっぱいになることがあります。これを防ぐには、コンピュータのメモリの現在の状態を監視し、不要なファイルを削除する必要があります。これらすべてが Java プログラミングとどのように関係するのでしょうか? かなり直接的に!結局のところ、オブジェクトを作成すると、Java マシンがそのオブジェクトにメモリを割り当てます。実際の大規模なプログラムでは、数万、数十万のオブジェクトが作成され、それぞれのオブジェクトに大量のメモリが割り当てられます。しかし、これらのオブジェクトは何個存在すると思いますか? プログラムの実行中、それらは常に「生きている」のでしょうか? もちろん違います。あらゆる利点があっても、Java オブジェクトは不滅ではありません :)オブジェクトには独自のライフサイクルがあります。 今日は、コードの作成から少し休憩して、このプロセスについて調べていきます :) これは、プログラムがどのように動作するかを理解し、リソースを管理するためにも非常に重要です。では、物体の一生はどこから始まるのでしょうか? 人間のように、生まれたときから、つまり創造されたときから。

Cat cat = new Cat();// Our Cat object's lifecycle begins now!
まず、Java 仮想マシンはオブジェクトの作成に必要なメモリを割り当てます。次に、それへの参照 (この場合はcat) を作成して、それを追跡できるようにします。次に、すべての変数が初期化され、コンストラクターが呼び出され、新しいオブジェクトが独自のライフサイクルを生き始めます :) オブジェクトのライフタイムはさまざまです。ここには正確な数字はありません。いずれにしても、オブジェクトはプログラム内に存在し、一定期間その機能を実行します。正確に言うと、オブジェクトへの参照がある限り、オブジェクトは「生きている」のです。参照がなくなるとすぐに、オブジェクトは「消滅」します。例えば:

public class Car {
  
   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}
このmain()メソッドでは、「Lamborghini Diablo」Car オブジェクトが 2 行目で生きなくなります。それへの参照は 1 つだけあり、その参照は null に設定されていました。ディアブロについては言及が残っていないので「ゴミ」となります。これを行うために参照をゼロに設定する必要はありません。

public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}
ここでは 2 番目のオブジェクトを作成し、それをランボルギーニ参照に割り当てました。ここで 2 つの参照がオブジェクトを指していますLamborghini Gallardoが、Lamborghini Diabloオブジェクトには何もありません。これは、Diabloオブジェクトがゴミになることを意味します。これは、Java の組み込みガベージ コレクター(GC) が作動するときです。
オブジェクトのライフサイクル - 2
ガベージ コレクターは、メモリを解放する、つまりメモリから不要なオブジェクトを削除する役割を担う内部 Java メカニズムです。それをロボット掃除機で表現したのには理由があります。ガベージ コレクターもほぼ同じように動作します。バックグラウンドでプログラムを「動き回って」、ガベージを収集します。実際にはそれを操作する必要はありません。その仕事は、プログラムで使用されなくなったオブジェクトを削除することです。したがって、他のオブジェクトのためにメモリを解放します。レッスンの冒頭で、実際にはコンピュータの状態を監視し、古いファイルを削除する必要があると述べたことを覚えていますか? Java オブジェクトについて話している場合、ガベージ コレクターがこれを実行します。。ガベージ コレクターはプログラムの実行中に何度も起動されます。明示的に呼び出してコマンドを与える必要はありません (ただし、これは技術的には可能です)。ガベージ コレクターについては後で詳しく説明し、その仕組みをさらに詳しく分析します。ガベージ コレクターがオブジェクトに到達すると、オブジェクトが破棄される直前に、そのオブジェクトの特別なfinalize()メソッドが呼び出されます。このメソッドを呼び出して、オブジェクトによって使用される特定の追加リソースを解放できます。メソッドfinalize()は Object クラスに属します。つまり、(以前に会ったことがある) と に似てequals()hashCode()ますtoString()すべてのオブジェクトにはそれがあります。他の方法と違うのは…なんというか…非常に意志が強いということです。つまり、オブジェクトが破棄される前に呼び出されるとは限りません。プログラミングは非常に精密な作業です。プログラマはコンピュータに何かをするように指示し、コンピュータはそれを実行します。皆さんはこの種の動作に慣れていると思いますので、最初は次の考えを受け入れるのが難しいかもしれません: 「オブジェクトが破棄される前に、Object クラスのメソッドが呼び出されるかどうか。運が良ければ! finalize()」 」それでも、これが現実なのです。Java マシン自体が、finalize() を呼び出すかどうかをケースバイケースで決定します。実験として、次のコードを実行してみましょう。

public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {

       for (int i = 0 ; i < 1000000; i++) {

           Cat cat = new Cat();
           cat = null;// The first object becomes available for garbage collection here
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("The Cat is destroyed!");
   }
}
オブジェクトを作成しCat、次の行でそのオブジェクトへの唯一の参照をゼロにします。そして私たちはそれを何百万回も繰り返します。このメソッドを明示的にオーバーライドしましたfinalize()。オブジェクトが破棄されるたびにCat、合計 100 万回、文字列を表示する必要があります。しかし、そうではありません。正確に言うと、私のコンピュータでは37346回しか実行されませんでした。つまり、私の Java マシンは、finalize()27 件中 1 件のみでメソッドを呼び出すことを決定しました。他のケースでは、ガベージ コレクションにはこの呼び出しは含まれませんでした。このコードを自分で実行してみてください。おそらく異なる結果が得られるでしょう。ご覧のとおり、finalize()信頼できるパートナーと呼ぶのは難しいです :) そこで、将来のための小さなヒントを紹介します。重要なリソースを解放する方法に依存しないでくださいfinalize()JVM がそれを呼び出す場合もあれば、呼び出さない場合もあります。知るか?オブジェクトが存続中にパフォーマンスに重要なリソース (オープンなデータベース接続など) を保持していた場合は、オブジェクトが不要になったときにリソースを解放するための特別なメソッドを作成し、明示的に呼び出した方がよいでしょう。そうすれば、プログラムのパフォーマンスが損なわれないことが確実にわかります。 メモリの操作とガベージ コレクションは非常に重要なトピックであるということから始めましたが、実際にそのとおりです。リソースの取り扱いを誤ったり、不要なオブジェクトのクリーンアップ方法を誤解したりすると、最も不快なバグの 1 つであるメモリ リークが発生する可能性があります。これは最もよく知られたプログラミング エラーの 1 つです。独自のウィキペディア記事もあります。コードが適切に書かれていないと、新しく作成されるオブジェクトには毎回メモリが割り当てられるが、古い不要なオブジェクトはガベージ コレクションに使用できないという状況が発生する可能性があります。すでにロボット掃除機の例えを作ったので、ロボットを動かす前に、靴下を家中に散らかし、ガラスの花瓶を割り、レゴのピースを床中に残したとしたら何が起こるかを想像してみてください。当然、ロボットは何かをしようとしますが、ある日突然動かなくなってしまいます。
オブジェクトのライフサイクル - 3
掃除機を適切に動作させるには、床を適切な形状に保ち、掃除機で処理できないものをすべて拾う必要があります。ガベージ コレクターも同じ原理に従います。プログラムにクリーンアップできないオブジェクト (靴下やロボット掃除機のレゴなど) が多数ある場合、いつかメモリ不足になります。プログラムがハングするだけでなく、コンピュータ上で実行されている他のすべてのプログラムもハングします。結局のところ、彼らには十分な記憶力もありません(先ほどの例え話に戻りますが、床に落ちた割れたガラスは掃除機だけでなく、家に住んでいる人たちも止まります)。つまり、Java におけるオブジェクトのライフサイクルとガベージ コレクションは次のようになります。これを暗記する必要はありません。仕組みを理解するだけで十分です。次のレッスンでは、これらのプロセスについては後で詳しく説明します。ただし、今のところは、CodeGym タスクの解決に戻ることができます :) 頑張ってください!
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION