Java仮想マシン(JVM)を読解しながら理解する #3
こちらの記事の続きです。
よんでいる公式ドキュメント
2.3. Primitive Types and Values(プリミティブ型と値)
この項目に関しては個人的に新しい情報というよりなんとなく把握している内容だったので、振り返りやすいように表にまとめておきました。
📌 数値型(Numeric Types)
整数型(2.3.1. Integral Types and Values)
| 型名 | ビット幅 | 表現形式 | 値の範囲 | デフォルト値 | 備考 |
|---|---|---|---|---|---|
byte |
8ビット | 符号付き2の補数 |
-128 ~ 127
|
0 |
|
short |
16ビット | 符号付き2の補数 |
-32,768 ~ 32,767
|
0 |
|
int |
32ビット | 符号付き2の補数 |
-2,147,483,648 ~ 2,147,483,647
|
0 |
|
long |
64ビット | 符号付き2の補数 |
-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
|
0L |
|
char |
16ビット | 符号なし整数(UTF-16) |
0 ~ 65535
|
'\u0000' |
Unicode BMP範囲のみ対象 |
浮動小数点型(2.3.2. Floating-Point Types and Values)
| 型名 | ビット幅 | IEEE 754準拠形式 | 精度(N) | 指数ビット(K) | Emax | Emin | デフォルト値 | 備考 |
|---|---|---|---|---|---|---|---|---|
float |
32ビット | binary32 (単精度) | 24 | 8 | +127 | -126 | 0.0f |
Float.NaN使用可 |
double |
64ビット | binary64 (倍精度) | 53 | 11 | +1023 | -1022 | 0.0d |
Double.NaN使用可 |
🔎 NaN(非数)や ±0、±∞ もJVMでは扱えます。
Javaの浮動小数点(
float,double)は、IEEE 754 規格に従っており、次のような特殊な値も表現できます:
+0.0(正のゼロ)と-0.0(負のゼロ) → 見た目は同じでも動作が異なることがある
- 例:
1.0 / +0.0→+Infinity、1.0 / -0.0→-Infinity
+Infinity(正の無限大) /-Infinity(負の無限大) → オーバーフロー時などに発生
NaN(Not-a-Number)→ 計算不能な場合の結果
- 例:
0.0 / 0.0やMath.sqrt(-1.0)⚠️
NaNは特殊な値で、次の特徴があります:
NaN != NaNは true → NaNは他のどんな値とも「等しくない」扱いNaN == NaNは falseNaNを含む計算や比較は、予期しない動作になることがあるため注意が必要✅ Javaでは
Float.NaN,Double.NaNが標準で提供されており、Float.isNaN(x)などで判定可能です。
🔁 returnAddress型(2.3.3. The returnAddress Type and Values)
| 型名 | 用途 | デフォルト値 | JVM命令との関係 | Java言語での扱い | 備考 |
|---|---|---|---|---|---|
returnAddress |
JVM命令へのポインタ(オペコード) | なし |
jsr, jsr_w, retなど |
使用不可 | JVM独自の制御用型。Javaコードからは利用不可 |
🧠 論理型(2.3.4. The boolean Type)
| 型名 | ビット幅 | 値の範囲 | デフォルト値 | JVM命令レベルでの扱い | 備考 |
|---|---|---|---|---|---|
boolean |
JVM依存 |
true, false
|
false |
専用命令はなし。intで代替 |
配列操作はbaload, bastoreを使用 |
Javaプログラミング言語では
booleanは型として扱われるが、JVMでは内部的にint型にマッピングされる。
2.4. Reference Types and Values(参照型と値)
JVMでは、reference型とは「オブジェクトや配列への参照」を扱う型のことです。Javaのあらゆるクラス・配列・インターフェース型はすべてこの reference型に分類されます。
🔷 reference型の3種類
| 型分類 | 説明 |
|---|---|
| クラス型 | 具体的なクラスに対応する型(例:java.lang.String) |
| 配列型 | 要素が配列として並ぶ型(例:int[], String[][]) |
| インターフェース型 | 実装クラスまたは配列が参照先となる型(例:List, Runnable) |
null参照とは?
-
reference型の変数は、オブジェクトを参照していない状態としてnullをとることができます。 -
nullは「どんな reference型にも代入できる特別な値」です。 -
null自体は 実行時型を持ちません が、任意の型にキャスト可能です。 -
reference型の変数のデフォルト値もnullです。 - JVM仕様上、
nullの内部表現(ビットパターンなど)は規定されていない。
・・・・なんとなく公式ドキュメントに記載されている内容を表にまとめていましたが
気になる要素が出てきました
JVM仕様上、
nullの内部表現(ビットパターンなど)は規定されていない。
ん?? どうゆこと??🤔
GPTに確認すると以下の内容が返ってきました
| 項目 | 内容 |
|---|---|
| 誰が決めるか? |
JVMの実装(例:HotSpot、OpenJ9、GraalVMなど) が null の内部表現(ビット列など)を決定します。 |
| JVM仕様では? |
null の具体的なビットパターンやメモリ上の値は 一切規定されていません。つまり「0である必要がある」などの決まりはありません。 |
| Javaバージョンとの関係 | Java SE 8、11、17、21など、すべてのバージョンにおいて null は「何も参照していない」ことを保証するだけであり、内部構造には言及しません。 |
💡 プログラマは
nullの値の中身(0なのか、特殊なビット列なのか)を気にする必要はなく、
単に「何も参照していない参照」として扱えばOKです。
とのこと・・・
HotSpot、OpenJ9、GraalVMという初見の単語が登場してきました・・・
| 項目 | HotSpot | OpenJ9 | GraalVM |
|---|---|---|---|
| 開発元 | Oracle | IBM(現在は Eclipse 財団) | Oracle Labs |
| 特徴 | - Java公式・標準実装 - 高速なJIT最適化 |
- 軽量で省メモリ - 高速起動・軽量JIT |
- 多言語対応(JavaScript, Python, etc.) - AOT(ネイティブ変換)対応 |
| 用途 | - 通常のJavaアプリ全般 - Spring Bootなど |
- コンテナ環境 - サーバレスやIoT |
- 起動速度・サイズが重要な環境 - マイクロサービス、AWS Lambda など |
| 備考 | - OpenJDK / Oracle JDKに採用 | - Adoptium(旧AdoptOpenJDK)で利用可能 | - native-imageで .exe などに変換可能 |
| 公式ドキュメント | HotSpot @ Oracle Docs | OpenJ9 @ Eclipse Docs | GraalVM @ Oracle Docs |
さて。。。まさかのJVMってOracleのみが作っているものだと思っていましたが、
Javaの仕様を満たしていれば誰でもJVMを実装してよく、さらにそのJVMで定義した内容によって
reference型のnullをどのようなビット列として扱うかは変わる(大体0らしい)つまり、JVMの実装依存とのこと・・・・
『参照型と値』の話から大きく離脱してしまいましたが、やはり知らないことばかりですね・・・・😇
ドキュメントを読んでみるのはやっぱり遅かれ早かれ必要なんだなと思う日々です。。。。
次のランタイムデータ領域の話はまた多くの情報がありそうなので翌週に回します!!
まとめ / 得た知見
-
nullに関しては「JVM仕様では内部ビット列は規定されていない」つまり、JVMの実装依存 - JVMには HotSpot(Oracle) 以外にも、OpenJ9(Eclipse財団) や GraalVM(Oracle Labs) などの実装があり、それぞれ特性が異なる
Discussion