ITエンジニアの成長ブログ

ITエンジニアとして行う勉強の発信&日々の生活で体験した楽しいことをゆるく発信

javacのオプション「-g」について

Javaで書いたプログラムのコンパイルは、「javac」コマンドによって行うことができます。
その「javac」コマンドのオプションのひとつに「-g」があります。今回はこのオプションについて調べたことを、この記事にまとめてみました。

今回の記事で使用するJavaバージョンは以下の通りです。環境は、Windows 11 Proになります。

Javaバージョン

javacのオプション「-g」とは?

javacコマンドを引数なしで実行することで、コマンドの使用方法を見ることができます。まずはそこから「-g」オプションの意味を見てましょう。

私の環境で実行した結果は以下の通りです。下の方に「-g」の説明が表示されていると思います。

javacコマンドの使用方法


「-g」は、”すべてのデバッグ情報を生成する”とあります。
他にも「-g:none」は、”デバッグ情報を生成しない”とあります。
また、「 -g:{lines,vars,source}」は、”いくつかのデバッグ情報のみを生成する”とあります。

デバッグ情報の生成をコントロールするオプションであることは分かりますが、そのデバッグ情報とは一体何で、どんな時に使えるものなのでしょうか。

実はこの情報は、例外発生時のスタックトレースに出力されるもののようです。
たとえば、以下は「Sample.java」というJavaプログラムで例外を発生させたものです。

例外発生時のスタックトレース

簡単に言えば、上記の”Sample.java:9”の出力部分を制御できる(このケースではSample.javaの9行目で例外が発生していることが分かる)のが、javacのオプション「-g」の役割のようです。
これだけでは意味が分からないと思いますので、実際に試してみます。

javacのオプション「-g」の使用方法

実際に試す前に、javacのオプションの「-g」の使用方法(というより、指定可能な書式)を以下に紹介しておきます。

Oracleの公式のjavacの「-g」オプションを抜粋したのが以下です。
The javac Command

Oracle公式のjavac「-g」オプション

デバッグ情報として表示できるものは以下の3つのようです。

キーワード 意味
lines 行番号のデバッグ情報
vars ローカル変数のデバッグ情報
source ソースファイルのデバッグ情報

また、デフォルトでは「lines」と「source」をデバッグ情報として表示するようです。

今回のJavaサンプルコード

これから実際にオプションを色々と試してみますが、使用するサンプルコードは以下です。

メソッド「method1」の最後のところで、NullPointerExceptionが発生するようになっています。

public class Sample {
	public static void main(String[] args) {
		method1();
	}
	
	private static void method1() {
		System.out.println("method1を呼び出しました");
		String str = null;
		System.out.println(str.toString());
	}
}

デバッグ情報を出力しない場合「-g:none」

デバッグ情報を出力しない場合は、javacのオプションに「-g:none」を指定します。

オプション「-g:none」でコンパイル

上記でコンパイルしたソースを実行した結果が以下です。

オプション「-g:none」で実行

どうでしょうか。例外のスタックトレースのメソッド名の括弧内に”Unknown Source”と記載されています。例外のクラスとメソッド名までは分かりますが、具体的なファイル名や行番号が表示されていません。

ソースファイルのデバッグ情報を出力する場合「-g:source」

ソースファイルのデバッグ情報を出力する場合は、javacのオプションに「-g:source」を指定します。

オプション「-g:source」でコンパイル

上記でコンパイルしたソースを実行した結果が以下です。

オプション「-g:source」で実行

どうでしょうか。例外のスタックトレースのメソッド名の括弧内に”Sample.java”と記載されています。例外が発生した具体的なファイル名が表示されていますが、行番号は表示されていません。

ソースファイルと行番号のデバッグ情報を出力する場合「-g:lines,source」

ソースファイルと行番号のデバッグ情報を出力する場合は、javacのオプションに「-g:lines,source」を指定します。

オプション「-g:lines,source」でコンパイル

上記でコンパイルしたソースを実行した結果が以下です。

オプション「-g:lines,source」で実行

どうでしょうか。例外のスタックトレースのメソッド名の括弧内に”Sample.java:9”と記載されています。例外が発生した具体的なファイル名と行番号が表示されています。すでに紹介しましたが、オプションを指定しなければこれがデフォルトの出力となります。

因みに、「-g:lines」のみを指定した場合も試したのですが「-g:none」と同じ出力結果となりました(つまり、"Unknown Source"と表示された)。確かに行番号だけだと、どのファイルか分からないので意味のない情報となるからですね。

すべてのデバッグ情報を出力する場合「-g」

すべてのデバッグ情報を出力する場合は、javacのオプションに「-g」を指定します。

オプション「-g」でコンパイル

上記でコンパイルしたソースを実行した結果が以下です。

オプション「-g」で実行

どうでしょうか。例外のスタックトレースのメソッド名の括弧内に”Sample.java:9”と記載されています。ここは既に紹介した「-g:lines,source」と変わりません。一体どこが変わったのでしょうか。

実は、この例外のエラーメッセージの部分になります。

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.toString()" because "str" is null

メッセージ最後の「~because "str" is null」の部分に注目してほしいのですが、"str"というローカル変数の名前が出力されています。

もう一度その前に実行した「-g:lines,source」のエラーメッセージを確認してみましょう。

オプション「-g:lines,source」で実行

"<local0>"という謎の名前になっています。ここが変わっているところです。つまり、「-g」ですべてのデバッグ情報を表示するとした場合には、キーワード「vars」が示すローカル変数のデバッグ情報を表示してくれているということですね。

まとめ

いくつかjavacのオプション「-g」の使い方を見てきました。

今まで見てきたようにこのオプションの意味は簡単に言えば、デバッグに関する情報の制御についてです。通常であれば、オプション(-g)を指定しないデフォルトのままで問題なさそうですね。

しかし、このオプションを指定してコンパイルした場合(もしくは無指定)はクラスファイルにそのデバッグ情報が追加されることになるので、ファイル容量が増えてクラスロードに影響が出る。みたいな記事をどこかで見かけました。信憑性は分かりませんが、無意味に「-g」ですべてのデバッグ情報を出力することはやめておいた方が良さそうです。

また、あえてすべてのデバッグ情報を出力しない選択も、もしかしたらあるかもしれません。例えば、あまり処理の内部を知られたくないケースではそうするのかもしれません。今後、Javaライブラリの例外のスタックトレース情報を気にかけておきたいと思います。

おわりに

いかがでしたでしょうか。私自身、数年はJavaに触れていましたがこのオプションの存在を最近知りました。通常であれば、あまり気にならない情報なので必要に迫られないと気づかないオプションかなと思います。

今回はこの辺で失礼いたします。最後までお読みいただきありがとうございました。