IDEやMavenはすべてのデバッグ情報を含めてコンパイルしてくれている


javacには-gというオプションがあります。これはクラスファイルへデバッグ情報を含めたり、逆に含めない設定をするためのオプションです。

  • -g:linesとすればソースコードの行番号を含めます
  • -g:varsとすればローカル変数名の情報を含めます
  • -g:sourceとすればソースファイル名を含めます
  • -gとすればすべてのデバッグ情報を含めます
  • -g:noneとすればデバッグ情報を何も含めません

次のようなコードをjavac -g Hello.javaしたとします。

public class Hello {
    public String say(String name) {
        return "hello ".concat(name);
    }
}

それからjavap -l Helloすると次のようになります(-lは行番号とローカル変数表を出力するオプションです)。

Compiled from "Hello.java"
public class Hello {
  public Hello();
    LineNumberTable:
      line 1: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       5     0  this   LHello;

  public java.lang.String say(java.lang.String);
    LineNumberTable:
      line 3: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       7     0  this   LHello;
          0       7     1  name   Ljava/lang/String;
}

LineNumberTableに行番号が、LocalVariableTableにローカル変数名が、そしてCompiled from 〜という箇所にソースファイル名が含まれています。

javac -g:none Hello.javaの場合はどうなるか。javap -l Helloしたものがこちらです。

public class Hello {
  public Hello();

  public java.lang.String say(java.lang.String);
}

デバッグ情報は何も含まれていません。

我々はふだん明示的にjavacをすることはなくEclipseやIntelliJ IDEAのようなIDEや、Mavenを使用してコンパイルしています。でも特に気にすることなくデバッグ時には対応するソースコードが勝手に開いて変数名を見ながらステップ実行ができるはずです。それはつまりIDEやMavenがデフォルトでデバッグ情報を含めてくれているということです。

Eclipseだとデバッグ情報を含めるかどうかを設定できます。デフォルトの状態をスクショしてみました。varslinessourceも含めるようになっていますね。

IntelliJ IDEAは使用していないので知らないのですが、おそらく似たような設定ができるんじゃないかなと思っています。

Mavenもデバッグ情報を含めるかどうかをmaven-compiler-pluginのdebugで設定できます

ちなみにjavac Hello.javaとした場合はソースファイル名と行番号が含まれます。つまりデフォルトでもjavac -g:source,lines Hello.javaと同じということですね。

以上をまとめると、

  • javac-gオプションでクラスファイルにデバッグ情報を含める
  • デフォルトではソースファイル名と行番号が含まれる
  • IDEやMavenはデフォルトでソースファイル名と行番号に加えてローカル変数名も含んでくれる

ということになります。