String Pool の仕組みを “やさしく深く” 理解する【Java内部構造の基礎】

🧠【初心者向け】String Pool をやさしく解説(図解あり)

Java の文字列は、他のオブジェクトとは少し違う特別な扱いを受けています。
その中心にあるのが String Pool(文字列プール) という仕組みです。

「String はなぜ不変なの?」
「同じ文字列リテラルが再利用されるってどういうこと?」
「new String(“abc”) と “abc” の違いは?」

そんな疑問に答えるため、
この記事では “初学者でも直感的に分かる図解” を交えながら、
String Pool の仕組みと実務への影響を整理します。


結論

・文字列リテラルは、すべて String Pool に保存・再利用される

・new String(“abc”) は Pool を使わず Heap に新規生成

・String が不変(immutable)なのは、Pool を安全に再利用するため


String Pool とは?

Java が JVM レベルで保持している “重複しない文字列の倉庫” です。

🔹図解(短線版)

String Pool
┌───────┐
│ "Hello"      │ ← リテラルはここに保存
│ "World"      │
│ "ABC"        │
└───────┘

Java はリテラル文字列を Pool に保存し、
同じ内容のリテラルが出てきた場合は 再利用 します。


なぜリテラルは再利用されるのか?(基礎)

理由は メモリ削減とパフォーマンス向上

String a = "hello";
String b = "hello";

a と b はどちらも Pool 内の 同じ “hello” を共有 します。

a ──▶ "hello" ◀── b

一度作った文字列を何度も再生成するのは無駄だからです。


new String(“abc”) が Pool を使わない理由

String s = new String("abc");

これは Heap に新しく文字列オブジェクトを作る 行為です。

図にするとこう👇

"abc"(String Pool)
        ↑
   new String("abc")
        ↓
Heap に新規オブジェクト

つまり:

  • Pool → あくまでもリテラル用
  • new → 必ず別オブジェクトを作る

String が不変(immutable)な理由

String が不変であることで以下が可能になります👇

  • Pool 内の文字列を 安全に共有
  • “破壊的変更” が起きないので スレッドセーフ
  • HashMap のキーなどで ハッシュ値が変わらない

もし String が可変だったら:

a → "abc"
b → "abc"

a が "xyz" に書き換わると b も変わってしまう

→ 破滅。

だから String は 不変である必要がある のです。


ここまでのまとめ(初心者向け)

  • リテラルは String Pool に保存され再利用
  • new String() は Pool を使わない
  • String が不変なのは Pool 共有・安全性のため
  • Pool を理解すると “文字列の挙動” が一気に読みやすくなる

▼▼ ここから深掘り・ニッチ編 ▼▼


【後半:ニッチ編】String Pool の内部構造と JVM の動き


intern() メソッドの本当の役割

intern() を使うと:

  • その文字列と同じ内容の文字列が Pool にある → それを返す
  • なければ 現在の文字列を Pool に登録して返す
String s = new String("hello");
String p = s.intern();

図で示すと👇

Pool: "hello"
        ↑
p ───┘
s(Heap)…別オブジェクト

つまり Heap → Pool の参照に切り替えるためのもの。


String Pool はどこに存在する?(JVM視点)

Java 7 以降、String Pool は Heap 上に配置 されています。
(Java 6 以前は PermGen 領域)

理由:

  • PermGen が小さすぎて OOM を起こしやすかった
  • Pool を Heap に置いたほうが管理しやすい

図解(短線版)

Heap
├ String Pool
│   ├ "A"
│   ├ "B"
│   └ "C"
└ 他のオブジェクト

パフォーマンス・メモリ観点での注意事項

✔ 大量の文字列を扱う場合

StringBuilder / StringBuffer を使うほうが効率的。

✔ Pool の使いすぎに注意

普通に使う分には問題ないが、
大量の intern() 連発は Heap を圧迫することがある。

✔ new String() を避ける

無駄にオブジェクトを増やすため、基本的には不要。


スレッド安全性との関係

Pool 内の文字列は 不変なのでスレッドセーフ

ただし:

  • Pool の遅延登録(intern動作)には内部ロックがある
  • 同時大量 intern はスケールしにくい

実務ではあまり問題にならないが知識として重要。


この記事のまとめ

  • String Pool は Java の文字列再利用の中核
  • リテラルは Pool、new は Heap
  • immutable である理由は “共有の安全性”
  • intern() は Heap→Pool の参照統一に使う
  • パフォーマンスや GC の理解にもつながる

Deep Friendly Tech の一言(後書き)

String Pool は、
「Java がなぜ安全で効率的なのか?」
という根本を支える存在です。

文字列はアプリケーションで最も使われるデータ型。
だからこそ、その裏側の仕組みを知っていると
コードの質・読み解く力・パフォーマンス理解 が一段アップします。

コメント

タイトルとURLをコピーしました