(自分向け)Javaのスタック領域とは

Javaのスタック領域を説明しようとした時にどうにもうまく説明できませんでした。

この記事では、
スタック・スタックフレーム・スタック構造・スタック領域など、スタックという単語が使われている物が多く、これらの混同を整理します。

参考書籍(2週間本はKindle Unlimitedで読み放題です)
※この記事は「この記事」を書いたNMRの考えを表しており、仮に内容が間違っていたとしても、参考書籍の筆者様達には一切責任はありません。

[スタック〇〇を整理する]

この後図解しますが手短に、
1.スタック=スタック構造=メソッドの先入れ後出し構造
2.スタック領域=スタックを扱うメモリ領域
3.スタックフレーム=メソッドの処理とメソッドが使う変数のセット

これを図解するとこうなります。

メソッドが実行されるとスタック領域というメモリ領域にスタックフレームが積み上げられていく。

1「処理の途中で2を呼び出して2の結果を1に戻してもらう。2の処理で得た結果と1でやりたい処理を実行した結果を表示する。」
2「1から頼まれた処理の途中で3を呼び出して3の結果を2に戻してもらう。3の処理を使ってだした結果を1に戻す。」
3「2に頼まれた処理をやって2に戻す。」

図の流れとしてはこんな感じに1→2→3とスタックフレームが積み上がり、3→2→1の順番でスタックフレームが処理されて行きます。

この辺に納得がいかないようであれば、Eclipseでmainメソッドとpublic staticで引数と戻り値があるメソッド2つを書いて処理順を確かめてみます。
何で?というよりはそうなってるというものだと思います。

※public staticであることは必須ではありません。単に動かしやすいかなと思っただけです。

次にスタックフレームの中身を覗いてみます。

実際に内部がこうなっているわけではありません。
スタックフレームにはメソッドの処理とローカル変数が入ってますよというイメージです。

実際にプログラミングする際は右のローカル変数の方しかほぼ考えていないと思います。

(qtyの四角に5を入れ忘れていますね。入ってる物としてください。)
Keisan();はint型の戻り値を返すだけのメソッドだと思ってください。

int result = Keisan();では、resultに結果を代入するためにKeisan();メソッドが呼び出され、スタックフレームが積み上がります。
前の画像で言うなら1→2の状態です。
2(Keisan();)が実行されると1(mainメソッド)に処理が戻りqty * resultの計算結果が出力されます。
これが2→1となる流れです。

(3つも例を出すのがめんどくさかったので1→2、2→1に省略しています。)

先に入れたものから詰みあがっていって、後に入れたものから出していくから先入れ後出しと言います。

[補足。画像からわかること]

同じスタックフレーム内では同じ名前の変数は使えないが、別のスタックフレームなら同じ名前の変数が使える。

例えるなら、
A「スタックフレームAの山田君」
B「スタックフレームBの山田君」
というように、どのスタックフレームにあるのか?で区別がつくからです。

また、スタックフレーム毎に分かれているので、なんとなくスタックフレームAはスタックフレームBの変数に直接アクセスできなさそうに見えるでしょう。そうです。なので引数が使われます。
(正確な理由としてはスタックフレームが分かれているからというよりはJavaのルールです。他の言語ではスタックフレームが分かれていても使える物もあるそうです。)

こんな感じでまとめてみました。

間違っているところがあれば優しく参考ソースつきで教えてくれれば幸いです。

リンクフリーです。引用する際は常識的な範囲で引用してください。

先人たちに敬意を込めて終わります。

この記事が気に入ったらサポートをしてみませんか?