ProgrammingJava開発者

Javaにおけるメモリ自動管理メカニズム(ガーベジコレクタ)はどのように機能しますか?

Hintsage AIアシスタントで面接を突破

回答

Javaでは、メモリの管理は自動ガーベジコレクション(Garbage Collector, GC)によって行われます。JVMはメモリ内のオブジェクトを自動的に追跡します:オブジェクトへの参照がなくなると、そのオブジェクトは到達不能となり、削除される可能性があります。

GCは、MarkSweep、および場合によってはCompactという異なるフェーズから成ります。Markフェーズでは、ルート(GC roots)から到達可能なオブジェクトが生きているものとしてマークされます。その後にSweepが始まります:未使用のオブジェクトが削除されます。時折、Compactが実行され、メモリの дефрагментацияが行われます。

GCにはさまざまなタイプがあり、Serial、Parallel、CMS、G1などがあります。これらはアプリケーションの負荷の種類に応じて選択するべきです。

コード例 - メモリリークの状況:
List<byte[]> dataList = new ArrayList<>(); while(true) { dataList.add(new byte[1024*1024]); // オブジェクトは到達可能を維持します }

この例では、オブジェクトは決して到達不能にならず、GCによって削除されず、OutOfMemoryErrorが発生します。

トリック質問

オブジェクトへの参照がなくなった場合、いつそのファイナライザ(finalize())の呼び出しが保証されますか?

回答: finalize()メソッドの呼び出しはまったく保証されません!一度も呼び出されないこともあれば、遅延が発生することもあります。リソースの解放にfinalize()を期待してはいけません。

@Override protected void finalize() throws Throwable { // 実行されない可能性があります! }

このトピックの微妙な知識から生じた実際のエラーの例


ストーリー

大規模なeコマースシステムで、開発者はfinalize()メソッドを使用して一時ファイルの自動クリーンアップを期待しましたが、このメソッドの呼び出しが稀であったため、キャッシュが一時ファイルで満たされ、ディスク不足とダウンタイムに繋がりました。


ストーリー

高負荷のREST APIで、大きなオブジェクトへの参照の内部キャッシュが偶然保存され、メモリ解放が妨げられました。アプリケーションがOutOfMemoryErrorで落ちた後、分析の結果キャッシングメソッドにエラーがあったことが判明しました。


ストーリー

ネットワーク接続を解放するためにファイナライザを使用し、「信頼できる方法」と見なしていました。これにより、接続が長期間システム内でハングし、ブロッキングや接続プールの枯渇を引き起こすことになりました。