akbピンボールマシン

RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

Javaのメモリ解放は誰がやっているのか

はじめまして!バックエンドエンジニアのnnhkrnkと申します!

先(xian)日組み込み系エンジニアの友人と話していた際、ではメモリをユーザが意(yi)図的に開放(fang)しないとが起きるということを初めて知りました。 自分は普段を書いてますが、メモリを意(yi)識(shi)してコーディングをしたことはほとんどありません。どのような仕組みになっているのか気になったため、におけるメモリ解放(fang)について調べてみました!

メモリ解放は誰がやっているのか

Cやではユーザが意図的にメモリ管理をする必要がありました。ではがその役割を担(dan)っています。メモリの使用や解(jie)放を自動で行ってくれるため、ユーザがメモリを意識せずにコーディングできるというわけです。

メモリ解放の仕組み

メモリ解放はの()という機能で行われています。 の処理を知(zhi)る前に、が管理するメモリ領域(yu)について整理していきましょう。

4種類のメモリ領域

プログラムが実行されると、のプロセスにメモリが割り与えられます。そのメモリ領域(yu)は以(yi)下(xia)の4つの領域(yu)に分(fen)けられます。

  • ヒープ領域
  • スタック領域
  • メタスペース
  • ネイティブメモリ(※ではなくOSが管理する領域)
領域 用途・特徴
ヒープ領域 生成されたの情報が保存される領域。
スタック領域 実行中のプログラムの情報が保存される領域。
実行中の行が「どこから呼び出されていて、どんな情報を参照可能か」などを持っているイメージ。
メタスペース クラス定義、メソッドコード、定数プールなどのクラス関連の情報が保存される領域。
ネイティブメモリ プログラムがネイティブコード(C、などで記述されたコード)を呼び出す際に使用される領域。
ではなくOSが直接管理をしている。

このうち、プログラム実行中にメモリ管(guan)理が必要になるのはヒープ領域(yu)になります。 では、このヒープ領域(yu)を対象としてメモリの管(guan)理を行っています。

ヒープ領域の詳細

ヒープ領域は大きく分けて以(yi)下の2つの領域で構成されています。

  • Young領域
  • Old領域
領域 特徴
Young領域 メモリに格納されてからの時間が比較的短いデータが格納されている領域。
新しく生成されたオブジェクトが一時的に配置される。
Old領域 メモリに格納されてからの時間が比較的長いデータが格納されている領域。
Young領域からのオブジェクトが長寿命のものとして移動する。

Young領域にはさらにEdenSurvivorの2つの領域に分けられます。 Survivorは領域が2つありますが、どちらも役(yi)割(ge)は同じです。

ヒープ領域の詳細

の処理の流(liu)れを理解する前(qian)に、には主に以下(xia)の2種(zhong)類があるということを押さえておきましょう。

の種類 対象領域 トリガー条件
マイナー Young領域(Eden領域、Survivor領域) Eden領域がいっぱいになった場合
フル ヒープ領域全体(Young領域とTenured領域) Tenured領域がいっぱいになった場合

マイナー

マイナーは以下のルールに沿ってメモリ解(jie)(jie)放(fang)を行います。 * Eden領(ling)域(yu)(yu)のデータ * データが不要(yao)(参照されてない)の場(chang)(chang)(chang)合、データを削(xue)除してメモリを解(jie)(jie)放(fang)する * データがまだ必要(yao)な場(chang)(chang)(chang)合、データをSurvivor領(ling)域(yu)(yu)に移(yi)動(dong)させてメモリを解(jie)(jie)放(fang)する * Survivor領(ling)域(yu)(yu)のデータ * データが不要(yao)の場(chang)(chang)(chang)合、データを削(xue)除してメモリを解(jie)(jie)放(fang)する * データがまだ必要(yao)な場(chang)(chang)(chang)合、データをもう片方のSurvivor領(ling)域(yu)(yu)かTenured領(ling)域(yu)(yu)に移(yi)動(dong)させてメモリを解(jie)(jie)放(fang)する

具体的に図で見ていきましょう。 が生成される、そのデータはEden領域に格納されます。 これが繰り返されるとEden領域がいっぱいになり、いずれはメモリが足りなくなってしまいます。 その際に実行されるのがマイナーです。

マイナー実行契機

実(shi)行開始後(hou)、Eden領域のデータがまだ参(can)(can)(can)照されているかどうかを確(que)認します。参(can)(can)(can)照されてない場(chang)合は削(xue)除(chu)、参(can)(can)(can)照されている場(chang)合はSurvivor領域に移動させることでメモリ解放を行います。

マイナーの処理(Eden領域)

同じタイミングでSurvivor領域のメモリ解放(fang)も行(xing)(xing)います。参(can)照(zhao)されてない場合(he)は削除することでメモリ解放(fang)を行(xing)(xing)い、まだ参(can)照(zhao)されている場合(he)はもう片方(fang)のSurvivor領域に移(yi)動することでメモリを解放(fang)します。

マイナーの処理(Survivor領域)

そのため、長い間解放されないデータは2つのSurvivor領域を行き来することになります。この回数には上限があり、上限を超えたデータはTenured領域に移動されるというわけです。

マイナーの処理(移動上限超過)

フル

マイナーを繰り返していくと、必要なデータが多く残っている場合にTenured領域がどんどん埋まっていってしまいます。 これを繰り返すと、マイナー実行時にTenured領域に空きがないために必要なデータを移動できないという事態が発生し、マイナー自体が失敗してしまいます。 その失敗を契機として実行されるのがフルです。

フル実行契機

Full では、YoungとOldの両(liang)方に対(dui)してメモリ解(jie)放(fang)を行います。Young領域に対(dui)してはマイナーと同じルールで実施(shi)し、Oldについては不要になったメモリを解(jie)放(fang)するというシンプルなルールです。

フルの処理

おわりに

今回はのメモリ解放について記載しました!
自分が普段メモリ解放を意識せずにプログラミングできているのはこのような便利な機能のおかげなんですね!勉強になりました!
それではまたの記事でお会(hui)いしましょう!

参考

以下の記事を参考にさせていただきました!ありがとうございました!





Copyright © RAKUS Co., Ltd. All rights reserved.