JavaRush /Java Blog /Random-JA /オブジェクトのライフサイクル

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

Random-JA グループに公開済み
こんにちは!コンピューターのメモリ サイズには限界があると言っても、あまり驚かないと思います :) RAM の何倍も大きいハード ドライブでさえ、お気に入りのゲーム、テレビ シリーズ、等々。これを防ぐには、メモリの現在の状態を監視し、コンピュータから不要なファイルを削除する必要があります。Java プログラミングはこれらすべてとどのような関係があるのでしょうか? 直接!結局のところ、Java マシンによってオブジェクトが作成されると、そのオブジェクトにメモリが割り当てられます。実際の大規模なプログラムでは、数万、数十万のオブジェクトが作成され、それぞれに独自のメモリが割り当てられます。オブジェクトのライフサイクル - 1しかし、これらすべてのオブジェクトはどれくらいの間存在すると思いますか? 彼らはプログラムの実行中ずっと「生きている」のでしょうか? もちろんいいえ。Java オブジェクトにはさまざまな利点がありますが、不滅ではありません :) オブジェクトには独自のライフサイクルがあります。今日はコードを書くことから少し休憩して、このプロセスを見ていきます :) さらに、これはプログラムの動作を理解し、リソースを管理するために非常に重要です。それでは、物の寿命はどこから始まるのでしょうか? 人と同じように、彼の誕生、つまり創造から。
Cat cat = new Cat();//вот сейчас и начался vital цикл нашего an object Cat!
まず、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 車のオブジェクトはすでに 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 番目のオブジェクトを作成し、その後参照を取得してlamborghiniこの新しいオブジェクトに割り当てました。Lamborghini Gallardoオブジェクトへの参照は 2 つありますが、オブジェクトLamborghini Diabloへの参照はありません。したがって、オブジェクトはDiabloゴミになります。そしてこの時点で、ガベージ コレクター、つまりガベージ コレクター (GC) と呼ばれる組み込み Java メカニズムが動作します。
オブジェクトのライフサイクル - 2
ガベージ コレクターは、メモリを解放する、つまりメモリから不要なオブジェクトを削除する役割を担う内部 Java メカニズムです。それを描くためにロボット掃除機の絵を選んだのは当然のことでした。結局のところ、ガベージ コレクターはほぼ同じように動作します。バックグラウンドでプログラム内を「移動」し、ガベージを収集しますが、同時にユーザーは実質的にガベージと対話しません。その仕事は、プログラムで使用されなくなったオブジェクトを削除することです。したがって、コンピュータ内のメモリが他のオブジェクトのために解放されます。講義の冒頭で、日常生活ではコンピュータの状態を監視し、古いファイルを削除する必要があると述べたのを覚えていますか? したがって、Java オブジェクトの場合は、ガベージ コレクターがこれを実行します。ガベージ コレクターはプログラムの動作中に何度も起動されます。技術的には可能ですが、特別に呼び出してコマンドを与える必要はありません。後ほど、これについて詳しく説明し、その作業プロセスをより詳細に分析します。ガベージ コレクターがオブジェクトに到達した瞬間、オブジェクトが破棄される直前に、そのオブジェクトに対して特別なメソッドが呼び出されますfinalize()。これを使用すると、オブジェクトが使用していた追加のリソースを解放できます。メソッドはfinalize()クラス に属しますObject。つまり、以前にすでに説明した 、equals()hashCode()とともに、どのオブジェクトにもそれがあります。toString()他の方法との違いは、それが...何と言いますか...非常に気まぐれであることです。つまり、オブジェクトを破棄する前に必ず呼び出されるとは限りません。プログラミングというのは精密なものです。プログラマはコンピュータに何かをするように指示し、コンピュータはそれを実行します。おそらく、この動作にはすでに慣れているので、最初は次の考えを受け入れるのが難しいかもしれません。「オブジェクトが破棄される前に、finalize()クラス メソッドが呼び出されます。オブジェクトが破棄される前に、クラスメソッドが呼び出されますObject。あるいは呼ばれていない。運が良ければ!」しかし、これは真実です。finalize()Java マシン自体が、特定のケースごとにメソッドを呼び出すかどうかを決定します。たとえば、実験のために次のコードを実行してみます。
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;//вот здесь первый an object становится доступен сборщику мусора
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("Объект Cat уничтожен!");
   }
}
オブジェクトを作成しCat、次のコード行でそのオブジェクトへの唯一の参照をリセットします。そして、何百万回も。メソッドを明示的にオーバーライドしましたfinalize()。オブジェクトを破棄する前に、毎回コンソールに文字列を 100 万回出力する必要がありますCat。しかし、そうではありません。正確に言うと、私のコンピューターでは 37,346 回しか実行されませんでした。つまり、インストールした Java マシンがメソッドの呼び出しを決定したのは 27 件中 1 件のみでした。finalize()他の場合は、これなしでガベージ コレクションが続行されました。このコードを自分で実行してみてください。おそらく、結果は異なります。ご覧のとおり、finalize()これを信頼できるパートナーと呼ぶのは難しいです :) したがって、将来のためのちょっとしたアドバイス:finalize()重要なリソースを解放する場合には、このメソッドに依存すべきではありません。おそらく JVM がそれを呼び出すかもしれませんが、呼び出さないかもしれません。知るか?オブジェクトが存続期間中に、パフォーマンスにとって非常に重要なリソースを占有している場合 (たとえば、データベースへの接続を開いたままにしている場合)、クラス内に特別なメソッドを作成してそれらを解放し、オブジェクトが終了したときにそれを明示的に呼び出すことをお勧めします。不要になりました。こうすることで、プログラムのパフォーマンスが低下しないことが確実にわかります。冒頭でメモリ管理とガベージの削除が非常に重要であると述べましたが、これは真実です。リソースが不適切に扱われたり、不要なオブジェクトを組み立てるプロセスが理解されていないと、メモリ リークが発生する可能性があります。これは最も有名なプログラミングの間違いの 1 つです。プログラマがコードを誤って作成すると、新しく作成されるオブジェクトに毎回新しいメモリが割り当てられる一方、古い不要なオブジェクトはガベージ コレクタによって削除できなくなります。ロボット掃除機を例に挙げたので、ロボットを起動する前に、靴下を家の中に散らかし、ガラスの花瓶を割って、分解したレゴセットを床に放置したらどうなるかを想像してみてください。もちろん、ロボットは何かをしようとしますが、ある時点で行き詰まってしまいます。
オブジェクトのライフサイクル - 3
正しく機能させるには、床を良好な状態に保ち、そこから掃除機が処理できないものをすべて取り除く必要があります。ガベージ コレクターも同じ原理で動作します。収集できないオブジェクトがプログラム内に多数残っている場合 (靴下やロボット掃除機のレゴなど)、ある時点でメモリが不足します。そして、作成したプログラムだけでなく、その時点でコンピュータ上で実行されている他のすべてのプログラムもフリーズします。彼らにとっても十分なメモリはありません。Java におけるオブジェクトのライフサイクルとガベージ コレクターは次のようになります。これを暗記する必要はありません。動作原理を理解するだけで十分です。次の講義では、これらのプロセスについて詳しく説明しますが、ここでは JavaRush の問題の解決に戻ってください :) 頑張ってください!
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION