JVMは、Java開発でバックエンドアプリケーションの起動によく使われるものです。しかし、JVMの仕組みがよくわからず、オプション設定の最適化に苦戦するエンジニアやIT関係者の方もいるでしょう。
そこで本記事は、JVMの仕組みやメモリ管理の方法について解説します。
目次
閉じる
1.JVM(Java Virtual Machine)とは
「JVM」は「Java Virtual Machine」を略した実行環境を用意するためのソフトウェアです。「Java VM」と呼ばれることもあります。直訳としては、「Java仮想マシン」です。
「Java」というプログラミング言語は、どのOS環境でも動作する設計思想のもとに開発されています。ソースコードを作成し、それをコンパイルすればどこでも実行できるマルチプラットフォーム対応となります。そのため、OSの違いを無視してJavaのアプリケーションを実行できる環境がこのJVMです。
業務上でJVMを使った開発の際は、システム最適化とリソース管理のスキルを高めるため、JVMの仕組みを理解する必要があります。
JVMの仕組み
Javaは、配布のために「Javaバイトコード」というものにコンパイルされます。その後、配布先の環境でJVMが機械語に変換して実行できる仕組みです。その際に、OSごとに別のソフトウェアを導入しなくても使えます。
以下にJVMでよく使う用語を簡単に説明しましょう。
Javaバイトコード
Javaバイトコードは、JVMで実行できるコードのことです。名称に「バイトコード」と付く理由は、情報量の「Byte(バイト)」で構成・実行されるためです。
具体的には「命令」と「パラメーター」の2種類のコードからできています。「命令長」(=命令の長さ)は1バイトに該当し、「パラメーター」が可変長です。
その上で、バイトコードは、ソースコードと機械語の間に位置する意味で「中間コード」と呼ばれます。
ネイティブコード
ソースコードがプログラミング言語で書かれた命令文なのに対し、ネイティブコードは機械語で書かれた命令文のことです。機械語は、マイクロプロセッサ(CPU)が直接的に実行が可能な言語です。
ネイティブコードの機械語は難解で、OSごとにマイクロプロセッサ(CPU)とその仕組も異なります。そのため、人が機械語を扱うのは通常難しく、人が理解できるソースコードのほうを使います。しかし、OS環境の違いからプログラミング言語でソースコードを書くだけではその差に対応しきれないため、中間コードや変換作業のできるコンパイラがあります。
コンパイラ
コンパイラは、Javaなどのプログラミング言語で書かれたソースコードをマイクロプロセッサ(CPU)が読み込めるように変換(コンパイル)するソフトウェアのことです。
JVM実行のためには、ファイル形式は「.java」から「.class」の状態にコンパイルして変更されます。これはJavaの特徴で、「.java」の拡張子ファイルを実行する前に必ずコンパイルが必要となるのです。
2.JVMの領域構成
JVMには、複数の領域が存在します。それがヒープ領域の「New領域」と「Old領域」、非ヒープ領域の「Permanent領域」です。
ヒープ領域
まずはJVMの領域を構成する「ヒープ領域」です。ヒープ領域とは、プログラム実行の際にリソースの解放や確保ができるメモリ領域を指します。いわゆる「ヒープメモリ」と呼ばれるものです。
JVMにはヒープ領域の区分として「New領域」と「Old領域」があります。この2つをまとめて扱い、メモリを割り当てたプールで管理します。
New領域
「New領域」とは、新たなオブジェクトを格納するためのメモリ領域のことです。細分化すると「Eden領域」と「From領域」、「To領域」から構成されています。
New領域では最初に、「Eden領域」を確保し、これがいっぱいになると「From領域」や「To領域」に入ります。オブジェクトの破棄と領域確保、コピー(移動)の実行をあわせて「コピー・ガーベージコレクション(コピーGC)」と呼んでいます。
Old領域
「Old領域」とは、New領域で確保したオブジェクトの領域から、破棄されずに長く残ったオブジェクトを格納するところです。「Tenured領域」とも呼ばれています。
このOld領域のメモリが満タンになると「フル・ガーベージコレクション(FullGC)」が発生します。このとき、新たにメモリを確保するための解放作業が実行されます。
しかし、この作業はアプリケーションを停止させるため、事前に回避する工夫が必要です。メモリのサイズ管理方法については後述します。
非ヒープ領域(Permanent領域)
非ヒープ領域は、ヒープ領域ではない別のメモリ領域のことです。JVMの場合、多大な量のクラス・メソッドをロードする際に、このPermanent領域に置かれる仕組みがあります。
ただし、Permanent領域はクラスの大量ロードでメモリ容量を圧迫するため注意が必要です。また、非ヒープ領域はJVM以外でも使用されているため、プログラム実行に不可欠な領域となります。
3.Javaで仮想環境構築の方法
Javaで仮想環境を構築するには、JVMの使える環境を用意する必要があります。以下に方法を解説します。
JVM(Java仮想マシン)標準装備のJDKをインストール
Javaは特別なコンパイラツールを除いて、JVMが必須です。そのため、Java環境を用意する際に、JDKをインストールした場合、JVMも一緒に入っています。
Java環境がない場合は、改めてOracle社の公式サイトから最新版JDKをダウンロードしてパソコンにインストールします。その際、要件(OSやWindowsならbit数など)を確認することです。
バージョンの確認
JDKをインストールしたら、コマンドプロンプトでJavaのバージョン確認を行います。コマンド画面に「java -version」と入れてエンターを押すだけで、バージョン情報が表示されます。そのバージョンの数字から最新版かどうかをチェックすることが可能です。
ただし、このバージョンが古いとJVMを起動できないことがあります。その際は、JDKのアップデートや再インストールを行います。
JVMの標準設定の確認
次に、JVMのオプション設定の確認です。まずはコマンドプロンプトから「java -help」を入力してエンターを押し、「標準オプション」の説明を確認します。
そこには「使用方法」や各種オプションが一覧に並び、使用できる標準オプションを確認できます。Javaでの仮想環境構築はJDKのインストール時に完了しているため、この確認手順はあくまでも補足的なものです。
ちなみに、開発環境(IDE)を構築したい場合は、別途インストールが必要となります。しかし、JVMの利用自体は、Eclipseなどの開発環境(IDE)でも環境変数の指定で実行可能です。
実行時にJVMの非標準設定を確認する
応用的な使い方や開発で活用したい方は、メモリ管理の使用方法や非標準設定のコマンドを表示して確認します。
表示方法は、コマンドプロンプトで「java -XshowSettings」と入れてエンターを押すだけです。「:all」を付け加えて全情報を出力したり、「java -XshowSettings:system」でシステム情報だけを部分的に表示したりもできます。メモリ設定の詳しい方法は後述します。
関連記事
Javaとは?Web開発で利用されるJavaの特徴や実行方法、おすすめ資格を解説
Java開発環境構築|Windows・Mac・Linux別開発環境手順とおすすめIDEを解説
4.JVM(Java VM)のメモリ設定の方法
JVMの仕組みやメモリなどを詳しく知ることは、効率的なシステム開発にとって有効です。なぜなら、システムの動作環境を最適化し、メモリを管理するためにはJVMの深い知識と理解が不可欠だからです。そこで、JVMのメモリを設定する方法について解説します。
JVMのメモリを管理する方法
JVMで実行する際、メモリを管理するには「Java -X」のオプションを使用することです。「Java -X」とは、Java環境の「-X」に関連した非標準オプションを指します。主に、ヒープ領域のメモリサイズを指す「ヒープサイズ」などを管理するものです。
ヒープサイズの上限数値の設定
ヒープサイズの上限は、必要に応じて数値を決めることができます。例えば、「java -Xmx512m MyApplication」と入力すれば、512MBにすることが可能です。
また、1GB(ギガバイト)にする場合は、「java -Xmx1g MyApplication」と1を入れて単位を「g」に変更します。単位変更なしでも、1GBに換算される1024MB(メガバイト)は「1024m」として設定することもできます。どちらも同じヒープサイズの設定値となります。2GBにしたいときは、2048MB(2048m)に置き換えることも可能です。
サイズが大きくなるほど、物理メモリ(RAM)不足のリスクが高まるため、実行内容を考慮して細かく数値を設定することが効率的なシステム開発では不可欠となります。
ちなみに、KB(キロバイト)の場合は「k」を単位とした設定です。また、Byte(バイト)の場合のみ、単位の記号はありません。
最大値の標準設定とエラー
ヒープ領域のメモリ最大値は、Windowsの場合、基本的に「32bit」のOS環境で初期値256MBの1GB、「64bit」のOS環境で初期値1GBの最大2GBで決まっています。標準の最大値以上を設定したい場合は、MBやGBでヒープサイズの値を自分で決めてオプションを設定することです。
最大値が不十分な場合、JVMが「OutOfMemoryError」をスローするエラーが発生します。スローとは、英語の「throw」のことで意図しない結果が発生したときに例外を投げることです。「Java -Xmx」の場合、ヒープ領域にメモリが不足して、オブジェクトを割り振れないことを意味します。
ただし、後述するように新世代のガベージコレクション(GC)で動的な場合は、初期値を無視しても問題ありません。
ピーク時やGC頻度を考慮した設計
「Java -Xmx」では、値を最適なものに設定するため、ピーク時やガベージコレクション(GC)の頻度、未解放のメモリ容量、実際の使用モデルを踏まえて設計します。想定では問題なくても、実際にリリースしてアプリケーションを使用した場合に問題が発生することもあるでしょう。
ヒープサイズの値の設定ミスは、さまざまな状況への最適化の不足が原因です。特にピーク時のメモリ不足で何度も起きる「OutOfMemoryError」のエラー発生は、ピークの見積もりが甘いことを意味します。設定の解析や見直しなどを実際にしながら、想定を踏まえて事前に値を決められるかで問題を回避することが可能です。
「ヒープサイズ」と「ガベージコレクション(GC)」の関係
「ヒープサイズ」と「ガベージコレクション(GC)」には、互いに大きく関係しています。まず、ヒープサイズのメモリ最大値が増大すると、「ガベージコレクション(GC)」の頻度が下がり、時間が長い状態が発生することです。逆に、最大値が低くなるほど頻度が増え時間が短くなります。
この仕組みは、バケツに水道水を入れるイメージで理解すると早いでしょう。大きなバケツは、水がいっぱいになると次のバケツに桶で移して、さらなる水道の水を受け入れます。
バケツが大きいほど、時間が長くなり、移し替えの間隔(蛇口をひねるまでの時間)は頻度が下がります。しかし、バケツが小さいと頻繁に移し替える必要が出てきます。そして、その時間は短くなります。
したがって、両者には深い関係性があります。「Java -Xmx」の具体的な上限値を決める際、ガベージコレクション(GC)の頻度や時間を想定するのは非常に重要なことです。
JVMでメモリ管理するときの注意事項
JVMでメモリ管理する際は、エラーや数値が反映されないトラブルが起こらないようにすることが大事です。例えば、以下のようなミスの回避です。
指定メモリサイズの前に半角スペースを空けていない(NG:「java -Xmx2g」)
記号ミス(NG:「java -Xmx 2C」)
物理メモリ(RAM)の推奨割合や上限を超える(NG:上限「2g」に対し、「4g」を設定する)
例えば、ヒープ領域は理論上で大きな値を入れられます。しかし、物理メモリ(RAM)を超えると、スワップ領域(仮想のメモリ容量)を使用し、この処理の速度が遅いため、アプリケーションの動作に支障が出やすくなります。リリース前に実際の使用を想定してメモリ管理・設定することです。
上限設定「-Xmx」以外の設定項目
ヒープ領域のメモリ容量は上限値だけでなく、ガベージコレクション(GC)やヒープサイズの最小値「-Xms」、ヒープの空き率「-XX:MaxHeapFreeRatio」(最大)と「-XX:MinHeapFreeRatio」(最小)、スレッドスタックのサイズを決める「-Xss」などが代表的です。
旧来は、初期値と最大サイズを決める「-Xmn」などもありましたが、新たな「G1ガベージコレクション(G1GC)」のように動的にサイズ調整できるようになったため、意味が薄くなって使われないオプションもあります。
また、速度に問題の発生しやすい「ヒープサイズ」と「ガベージコレクション(GC)」に対して、ZGCの「-XX:+UseZGC」を設定することで以前よりもパフォーマンスを上昇させることができます。
これは新しいZGCの特徴で、GCスケーリングやサイズの変更調整、「1ミリ秒」を超過して停止しない高負荷作業を同時に実行する仕様です。最大値を増やして最適化する自動のパフォーマンスチューニングが可能となります。
関連記事
【2025年版】Javaの最新バージョン|確認方法やインストール方法を解説
Javaコマンドを実行する方法|ファイルのコマンドプロンプト操作手順や対処法、オプション一覧を解説
5.よくあるJVMに関する質問
ここでは、JVMの使用でよくある疑問や質問に回答します。
JVMはJavaのプログラミング言語のみを扱う?
JVMはJavaだけでなく、PythonやRuby、Kotlin、Clojure、Groovy、Scalaなど複数のプログラミング言語を実行可能です。JVMでは、元の「ソースファイル」を「Javaバイトコード」に変換した「バイトコード」のクラスファイルさえあれば、元のソースファイルがJavaで書かれてなくても実行できます。
JVMとJREの違い
JVMとJREは、実行環境のソフトウェアという点でどちらも同じです。しかし、それぞれ示す範囲が違います。Javaの環境構築では、JDKをインストールすることで、JVMとJREも同時に導入できます。
このとき、JVMはJREの中に入っているため、まったくの別物ではなく、JREの一部といえます。あくまでも、アプリケーションを実行する環境「JRE」の中の1つで、仮想環境を構築するのがJVMです。
JVMとTomcatの関係は?
Tomcatは、JVM上で動作するWEBアプリケーションサーバーの実行ソフトウェアです。特に、コンテナ(サーブレット)でWEBブラウザで実行するサーバーの機能を有しています。
そのため、Tomcatのインストール時は、JVMのメモリ割り当てのオプション設定などを施します。つまり、互いの関係は、Tomcatのソフトウェアを使用する土台としてJVMが不可欠です。
6.まとめ
今回は、JVMの特徴やインストール方法、メモリ設定の仕方まで解説しました。JVMではコンパイルを入れた中間コードを機械語に変換できる機能を持ち、どのOS環境でも実行することができます。
特にメモリ設定は、システム最適化とリソース管理のスキルアップや実務でのトラブルシューティングにはなくてはならない知識です。
基本を押さえて、オプション設定の実践やメモリの最適化などに取り組みましょう。
本記事が皆様にとって少しでもお役に立てますと幸いです。