Javaの特徴とJVMのコードトレース

Javaを、言語・コンパイラ・仮想マシン・標準APIの組合せとして理解します。ソースから実行までの役割を分け、移植性の条件とJava SE・EE・MEの位置付けを学びます。

この単元で学ぶこと

  • 起動時のクラス初期化とmainの順を追う
  • コンパイルと実行時の異なる失敗を区別する
  • Javaの整数・参照・APIの実行規則を具体例に適用する

本文解説

初期化とmainの順 クラスにstatic{System.out.print("S");}がありmainがMを表示するなら、起動時にはSMの順になります。起動クラスの初期化はmainの呼出しより先です。ソースの下にmainがあるからという文字上の位置だけで順番が決まるわけではありません。

staticフィールドの準備 static int n=3;static{n+=2;}の後でmainからnを読むと5です。フィールド初期化子とstatic初期化子はクラス初期化の段階で処理されます。同じクラスに実体を二つ作っても、static初期化を実体ごとに繰り返すものではありません。

実体の生成で動く処理 インスタンス初期化子やコンストラクタはnewしたときに動きます。mainの起動だけで自動的にMainのコンストラクタが呼ばれるわけではありません。new Main()を二回書けば、コンストラクタも二回動きます。

型違反は実行前に止まる int n="3";という代入は、Stringをintへ暗黙に変換できずコンパイルで拒否されます。JVMが文字の見た目を見て実行中に数値へ直してくれるわけではありません。文字列から整数への変換はparseIntなどを明示的に呼びます。

実行時に起きる失敗 int[] a={1};System.out.print(a[1]);は型としては成立しますが実行時に範囲外です。null参照でインスタンス操作を呼ぶ場合も、参照型としてのコンパイルと実体の存在は別の検査です。エラーの段階を区別します。

整数の規則は固定 intの演算は32ビットの符号付き整数として定められます。Integer.MAX_VALUEに1を足すと最小値へ回り、例外で停止するわけではありません。OSのビット数が違うからintの幅を任意に変えることはできません。

参照と自動メモリ管理 Box a=new Box();Box b=a;は同じ実体を指します。a=nullとしてもbが参照している実体は引き続き使えます。変数をnullへ代入することとオブジェクトの消滅は同じ操作ではなく、ガベージコレクションの時刻をこの代入だけから断定できません。

標準APIを呼ぶ "abc".length()は3、Integer.parseInt("12")+1は13です。言語の構文でメソッドを呼び、その意味はAPIが定めます。整数演算や文字列操作の結果を追いながら、APIとJVMと自分のmainの役割を混同しないようにします。

図解

コードの実行開始を追う
インスタンス初期化はその実体を生成した時に行う。

重要ポイント

  • javacがソースをクラスファイルへ変換し、javaが実行環境を起動する。
  • JVM実装は環境に対応し、クラスファイルは共通の形式を持つ。
  • 互換バージョン・必要ライブラリ・外部環境が実行条件になる。
  • SEは基礎、EEは企業向けの拡張、MEは小型機器向けの構成。

間違えやすい点

  • どのOSでも無条件に動くと断定しない。
  • JVMを必ず逐次インタプリタだけと考えない。
  • SE/EE/MEを難易度や速度の順位と考えない。

用語解説

JVM
クラスファイルに記された命令等を扱う仮想マシン。
JDK
コンパイラ等の開発用ツールを含む開発キット。
API
プログラムから利用できるクラスやメソッド等の取り決め。
バイトコード
JVMが扱う命令形式。クラスファイルに収録される。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。