Java コードのコンパイル

JDT プラグインには、ソース・コードから Java の .class ファイルをビルドするためのインクリメンタル Java コンパイラーおよびバッチ Java コンパイラーが含まれています。 このコンパイラーは、直接 API を提供していません。 直接 API は、Java プロジェクトに対するビルダーとしてインストールされます。 コンパイルは、プラットフォームの標準のビルド・メカニズムを使用して起動されます。

プラットフォームのビルド・メカニズムについては、 「インクリメンタル・プロジェクト・ビルダー」で詳細に説明されています。

コードのコンパイル

ビルド API を使用して、プロジェクトの Java ソース・ファイルをプログラマチックに コンパイルすることができます。

   IProject myProject;
   IProgressMonitor myProgressMonitor;
   myProject.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, myProgressMonitor);

Java プロジェクトの場合、このコードにより Java インクリメンタル・プロジェクト・ビルダーが (プロジェクトのビルド・スペックに追加されている他のすべてのインクリメンタル・プロジェクト・ビルダーとともに) 起動されます。 生成された .class ファイルは、指定の出力フォルダーに書き込まれます。 その他のリソース・ファイルも出力フォルダーにコピーされます。  

フル・バッチ・ビルドの場合、不整合ファイルが見つからなくなるように出力フォルダー内のすべての .class ファイルが「修正」できます。 これは、JDT コア・ビルダー・オプション (CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER) を使用して制御できます。  このオプションのデフォルトは、出力フォルダーのクリーンです。 このオプションがリセットされていない限り、対応するソース・ファイルがない .class ファイルはすべて、 出力フォルダーではなくクラスパスの別のクラス・ファイル・フォルダーに入れる必要があります。

インクリメンタル・ビルダーおよびバッチ・ビルダーは、 どのリソースを出力フォルダーにコピーするかを制御する他のオプションを使用して構成できます。 次のサンプルは、「.ignore」で終わるファイルと「META-INF」という名前のフォルダーが出力フォルダーにコピーされないようにリソース・フィルターをセットアップする方法を示しています。

      Hashtable options = JavaCore.getOptions();
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   JavaCore.setOptions(options);

指定されたいずれかのパターンにファイル名が一致する場合、ファイル名がフィルターに掛けられます。 フォルダー名が、パス・セパレーターで終わる指定のフォルダー名のいずれかと一致する場合、 そのフォルダー全体がフィルターに掛けられます。

インクリメンタル・ビルダーおよびバッチ・ビルダーは、.classpath ファイルにエラーがあるときに 1 つのエラーのみを生成するように構成することもできます。 このオプションはデフォルトで設定され、多くのエラーを除去します。   ビルダー関連オプションとそのデフォルトの詳細なリストについては、『JDT コア』のビルダー・オプションを参照してください。

コンパイラーは、JavaCore を使用して構成することもできます。 例えば、コンパイル中に見つかるさまざまな種類の問題に使用する重大度を定義できます。   コンパイラー関連オプションとそのデフォルトの詳細なリストについては、『JDT コア』のコンパイラー・オプションを参照してください。

ビルダーまたはコンパイラーのオプションをプログラマチックに構成する場合は、 オプションのスコープを指定する必要があります。   例えば、リソース・フィルターのセットアップが、特定のプロジェクトにのみ適用される場合があります。

   
   Hashtable options = myProject.getOptions(false);  // get only the options set up in this project
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   myProject.setOptions(options);

バッチ・コンパイラーの使用

バッチ・コンパイラーの検索

バッチ・コンパイラー・クラスは、 JDT コア・プラグインの内部クラスに配置されています。 クラスの名前は、org.eclipse.jdt.internal.compiler.batch.Main です。 これは plugins/org.eclipse.jdt.core_3.2.0.jar にパッケージされています。3.2 以降、個別にダウンロードして入手できるようになりました。 ファイル名は ecj.jar です。この対応するソースも使用可能です。これを入手するには、download page にアクセスして、セクション 「JDT コア・バッチ・コンパイラー (JDT Core Batch Compiler)」を検索します。この jar にはバッチ・コンパイラーと javac Ant アダプターが含まれています。

このため、スタンドアロンのアプリケーションとして、Eclipse 外部の Ant ビルド内部で使用できます。

バッチ・コンパイラーの実行

使用可能なオプション

背景がオレンジ色の箇所が、推奨のオプションです。

名前 使用法
クラスパス・オプション
-bootclasspath <dir 1>;<dir 2>;...;<dir P> これは、コンパイラーにより使用されるクラス・ファイルのブートストラップに使用されるディレクトリーまたは JAR ファイルのリストです。 デフォルトで、実行中の VM のライブラリーが使用されます。 エントリーは、プラットフォームのパス・セパレーターにより分離されます。
各ディレクトリーまたはファイルでは、「[」と「]」の間でタイプのアクセス規則を指定することができます。
-cp
-classpath <dir 1>;<dir 2>;...;<dir P>
これは、ソース・ファイルのコンパイルに使用されるディレクトリーまたは JAR ファイルのリストです。 デフォルト値は、プロパティー "java.class.path" の値です。 エントリーは、プラットフォームのパス・セパレーターにより分離されます。
各ディレクトリーまたはファイルでは、「[」と「]」の間でタイプのアクセス規則を指定することができます (例えば、[-X] はタイプ X へのアクセスを禁止し、[~X] はタイプ X へのアクセスを非推奨とし、[+p/X:-p/*] はパッケージ p のすべてのタイプへのアクセスを禁止しつつ p/X へのアクセスを許可します)。
-extdirs <dir 1>;<dir 2>;...;<dir P> これは、拡張 ZIP/JAR ファイルの場所の指定に使用されるディレクトリーのリストです。 エントリーは、プラットフォームのパス・セパレーターにより分離されます。
-endorseddirs <dir 1>;<dir 2>;...;<dir P> これは、承認済み ZIP/JAR ファイルの場所の指定に使用されるディレクトリーのリストです。 エントリーは、プラットフォームのパス・セパレーターにより分離されます。
-sourcepath <dir 1>;<dir 2>;...;<dir P> これは、ソース・ファイルの指定に使用されるディレクトリーのリストです。 エントリーは、プラットフォームのパス・セパレーターにより分離されます。
各ディレクトリーまたはファイルでは、「[」と「]」の間でタイプのアクセス規則を指定することができます。
-d <dir 1>|none これは、生成された .class ファイルがダンプされるディレクトリーの指定に使用されます。 省略された場合、パッケージのディレクトリー構造は作成されません。
.class ファイルを全く生成しない場合は、-d none を使用してください。
-encoding <encoding name> デフォルトのソース・エンコード・フォーマットを指定します (それぞれの入力ソース・ファイル/フォルダー名に、例えば X.java[utf8] のように [<encoding name>] のサフィックスを付けることにより、ファイルごとにカスタム・エンコードを指定することもできます)。
準拠オプション
-target 1.1|1.2|1.3|1.4|1.5|5|5.0|1.6|6|6.0 .class ファイルのターゲット設定を指定します。 指定可能な値は以下のとおりです。
  • 1.1 (メジャー・バージョン: 45 マイナー: 3)
  • 1.2 (メジャー・バージョン: 46 マイナー: 0)
  • 1.3 (メジャー・バージョン: 47 マイナー: 0)
  • 1.4 (メジャー・バージョン: 48 マイナー: 0)
  • 1.55 または 5.0 (メジャー・バージョン: 49 マイナー: 0)
  • 1.66 または 6.0 (メジャー・バージョン: 50 マイナー: 0)
デフォルトは以下のとおりです。
  • 1.1-1.3 モードの場合
  • 1.2-1.4 モードの場合
  • 1.5-1.5 モードの場合
  • 1.6-1.6 モードの場合
-1.3 準拠レベルを 1.3 に設定します。-source 1.3 -target 1.1 を暗黙的に設定します。
-1.4 準拠レベルを 1.4 に設定します (デフォルト)。-source 1.3 -target 1.2 を暗黙的に設定します。
-1.5 準拠レベルを 1.5 に設定します。-source 1.5 -target 1.5 を暗黙的に設定します。
-1.6 準拠レベルを 1.6 に設定します。 -source 1.6 -target 1.6 を暗黙的に設定します。
-source 1.3|1.4|1.5|5|5.0|1.6|6|6.0 これは、コンパイラーによって予想されるソース・レベルを指定するのに使用します。
指定可能な値は以下のとおりです。
  • 1.3
  • 1.4
  • 1.55 または 5.0
  • 1.66 または 6.0
デフォルトは以下のとおりです。
  • 1.3-1.3 モードの場合
  • 1.3-1.4 モードの場合
  • 1.5-1.5 モードの場合
  • 1.6-1.6 モードの場合
1.4 では、assert がキーワードとみなされます。1.5 および 1.6 では、enum および assert がキーワードとみなされます。
警告オプション
-warn:
allDeprecation
allJavadoc
assertIdentifier
boxing
charConcat
conditionAssign
constructorName
dep-ann
deprecation
discouraged
emptyBlock
enumSwitch
fallthrough
fieldHiding
finalBound
finally
forbidden
hiding
incomplete-switch
indirectStatic
intfAnnotation
intfNonInherited
javadoc
localHiding
maskedCatchBlocks
nls
noEffectAssign
null
over-ann
paramAssign
pkgDefaultMethod
raw
semicolon
serial
specialParamHiding
static-access
staticReceiver
suppress
synthetic-access
syntheticAccess
tasks(<task1>|...|<taskN>)
typeHiding
unchecked
unnecessaryElse
unqualified-field-access
unqualifiedField
unused
unusedArgument
unusedImport
unusedLabel
unusedLocal
unusedPrivate
unusedThrown
uselessTypeCheck
varargsCast
warningToken
警告レベルを設定します。
例: -warn:unusedLocal,deprecation

赤色 の部分はデフォルトの設定値です。

  -warn:none                          すべての警告を使用不可にします
    -warn:<, で区切られた警告>    リストされた警告のみを使用可能にします
    -warn:+<, で区切られた警告>   追加の警告を使用可能にします
    -warn:-<, で区切られた警告>   指定された警告を使用不可にします
allDeprecation 使用されないコード内でも使用すべきではない
allJavadoc javadoc が無効または欠落
assertIdentifier 識別子として使用された assert の発生
boxing オートボクシング型変換
charConcat 文字配列が文字列に明示的に変換されることなく、文字列の連結で使用された場合
conditionAssign 予期しないブールの代入
constructorName コンストラクター名を持つメソッド
dep-ann @Deprecated 注釈の欠落
deprecation 使用すべきでないコード外部での使用すべきでないタイプまたはメンバーの使用
discouraged 阻止されるアクセス規則に一致するタイプの使用
emptyBlock 文書化されていない空のブロック
enumSwitch、
incomplete-switch
不完全な列挙スイッチ
fallthrough case のフォールスルーの可能性
fieldHiding 別の変数が非表示のフィールド
finalBound 最終バウンドがあるタイプ・パラメーター
finally 正常に完了していない finally ブロック
forbidden 禁止されるアクセス規則に一致するタイプの使用
hiding fieldHiding、localHiding、typeHiding および maskedCatchBlock のマクロ
indirectStatic 静的メンバーへの間接参照
intfAnnotation スーパー・インターフェースとして使用される注釈型
intfNonInherited インターフェースを継承しないメソッドの互換性
javadoc 無効な javadoc
localHiding 別の変数が非表示のローカル変数
maskedCatchBlocks 隠れた catch ブロック
nls 非 nls の文字列リテラル (タグ //$NON-NLS-<n> が欠如)
noEffectAssign 効果のない代入
null NULL 検査が欠落または冗長
over-ann @Override 注釈の欠落
paramAssign パラメーターへの代入
pkgDefaultMethod パッケージのデフォルト・メソッドを無効にする試行
raw raw 型の使用 (パラメーター型の代わりに)
semicolon 不要なセミコロンまたは空のステートメント
serial serialVersionUID の欠落
specialParamHiding 別のフィールドを非表示にするコンストラクターまたは setter パラメーター
static-access indirectStatic および staticReceiver のマクロ
staticReceiver 静的フィールドの取得または静的メソッドの呼び出しに、静的ではない受信側が使用された場合
suppress @SuppressWarnings を使用可能にする
syntheticAccess、
synthetic-access
内部クラスに対して合成アクセスを実行する場合
tasks ソース・コード内でのタスク・タグのサポートを可能にする
typeHiding 別のタイプが非表示のタイプ・パラメーター
unchecked 未検査の型操作
unnecessaryElse 不要な ELSE 節
unqualified-field-access、
unqualifiedField
フィールドへの非修飾参照
unused unusedArgument、unusedImport、unusedLabel、unusedLocal、unusedPrivate および unusedThrown のマクロ
unusedArgument 未使用のメソッド引数
unusedImport 未使用のインポート参照
unusedLabel 未使用ラベル
unusedLocal 未使用のローカル変数
unusedPrivate 未使用の private メンバー宣言
unusedThrown 未使用で宣言済みのスローされた例外
uselessTypeCheck 不要な cast/instanceof 演算命令
varargsCast 可変引数に明示的なキャストが必要
warningToken @SuppressWarnings での処理されない警告トークン

-nowarn 警告なし (-warn:none と同等)
-deprecation -warn:deprecation と同等
デバッグ・オプション
-g[:none|:lines,vars,source] デバッグの属性レベルを設定します
-g すべてのデバッグ情報 (-g:lines,vars,source と同等)
-g:none デバッグ情報なし
-g:[lines,vars,source] 選択的なデバッグ情報
-preserveAllLocals すべてのローカル変数を保持することをコンパイラーに明示的に要求 (デバッグの目的)。 省略した場合、コンパイラーは未使用のローカル変数を除去します。
無視されるオプション (javac オプションとの互換用)
-J<option> 仮想マシンにオプションを渡す
-X<option> 標準外のオプションを指定。 -Xemacs は無視されません。
-X 標準外のオプションを印刷して終了
-O 実行時の最適化
拡張オプション
@<file> ファイルからコマンド行の引数を読み取ります
-maxProblems <n> コンパイル単位ごとの問題の最大数 (デフォルトは 100)
-log <filename> コンパイラーからのすべての出力がダンプされるログ・ファイルを指定します。 これは、バッチ・コンパイラーをデバッグする場合や、バッチのビルドからすべてのエラーおよび警告が含まれたファイルを取得する場合、非常に役に立ちます。 拡張子が .xml の場合、生成されるログは xml ファイルになります。
-Xemacs emacs スタイルを使用してエラーと警告のロケーションをコンソールおよび通常のテキスト・ログに表示します。 XML ログは、このオプションによって影響を受けません。このオプションをアクティブにすると、With this option
2. WARNING in /workspace/X.java
(at line 8)...

というメッセージが、以下のように表示されます。
/workspace/X.java:8: warning: The method...
-proceedOnError エラーが起こってもコンパイルを継続し、問題のメソッドまたは型があるクラス・ファイルをダンプします。これが推奨されるのは、エラーが残っていてもそのアプリケーションを実行する必要がある場合のみです。
-verbose コンソールまたはログ・ファイル (指定された場合) に、アクセス/処理されたコンパイル単位を出力します
-referenceInfo 参照情報を計算します。 これは、ビルダーに接続されている場合にのみ有用です。 それ以外の場合、参照情報は役に立ちません。
-progress 進行状況を表示します (-log モード時のみ)。
-time 速度情報を表示します。
-noExit コンパイルの最後に System.exit(n) を呼び出しません (エラーがない場合は n=0)。
-repeat <n> コンパイル処理を <n> 回繰り返します (パフォーマンス分析)。
-inlineJSR JSR バイトコードをインライン化します (target >= 1.5 の場合は暗黙)。
-enableJavadoc javadoc 内部の参照を考慮します。
ヘルプ・オプション
-? -help ヘルプ・メッセージを表示します。
-v -version コンパイラーのビルド番号を表示します。 これは、バグを報告する場合に非常に有用です。
-showversion コンパイラーのビルド番号を表示し、継続します。 これは、バグを報告する場合に非常に有用です。

d:¥temp -classpath rt.jar -time -g -d d:/tmp d:¥temp およびそのサブフォルダー内のすべてのソース・ファイルをコンパイルします。 クラスパスは、単に rt.jar です。 すべてのデバッグ属性を生成し、生成されたすべての .class ファイルが d:¥tmp にダンプされます。 コンパイラーの速度は、バッチ・プロセスの完了後に表示されます。
d:¥temp¥Test.java -classpath d:¥temp;rt.jar -g:none Test.java およびその従属ファイル (ある場合は、d:\temp から従属ファイルを取得します) のみをコンパイルします。クラスパスは d:\temp の後に rt.jar が付きます。これは、すべての必要なクラスが最初に d:\temp、次に rt.jar で検索されるということです。デバッグ属性は生成されず、生成されたすべての .class ファイルが d:\temp にダンプされます。

ant javac アダプターの使用

Eclipse コンパイラーは、javac アダプターを使用する Ant スクリプト内で使用できます。 Eclipse コンパイラーを使用するには、スクリプトに build.compiler プロパティーを正しく定義する必要があります。 以下に、簡単な例を示します。
<?xml version="1.0" encoding="UTF-8"?>
<project name="compile" default="main" basedir="../.">

	<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>

	<property name="root" value="${basedir}/src"/>

	<property name="destdir" value="d:/temp/bin" />

	<target name="main">
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
		    <classpath>
		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
		    </classpath>
		</javac>		
	</target>
</project>
javac Ant タスクで使用される構文は、 『Ant javac タスク・ドキュメンテーション』にあります。 現行アダプターは、Javac Ant タスク 1.4.1 から 1.6.5 までのバージョンをサポートしています。

1.5.0 より後のバージョンを使用している場合は、コンパイラー固有のオプション指定に、ネストされたコンパイラー引数要素を使用できます。

...
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
		    <classpath>
		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
		    </classpath>
    <compilerarg compiler="org.eclipse.jdt.core.JDTCompilerAdapter" line="-1.5 -warn:+boxing"/>
</javac>		
...

コンパイラーに依存するスクリプトの取得を避けるため、org.eclipse.jdt.core.JDTCompilerAdapter に設定したコンパイラー引数を使用することを推奨します。 これが設定されない場合、そのスクリプトは Eclipse コンパイラーでのみ使用可能です。 設定されると、build.compiler プロパティーによって指定されたコンパイラー名と名前が異なる場合に、ネストされたコンパイラー引数は無視されます。

問題判別

JDT コアは、コンパイルの問題を示すための特別なマーカー (org.eclipse.jdt.core.problem というマーカー型) を定義します。 コンパイラーによって検出された問題を方針に基づいて発見するには、 プラットフォームの標準のマーカー・プロトコルを使用する必要があります。 マーカーの使用方法の概要については、 『リソース・マーカー』を参照してください。

以下のコードのスニペットにより、コンパイル単位内のすべての Java 問題のマーカーが検出されます。

   public IMarker[] findJavaProblemMarkers(ICompilationUnit cu)
         throws CoreException {
      IResource javaSourceFile = cu.getUnderlyingResource();
      IMarker[] markers =
         javaSourceFile.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,
            true, IResource.DEPTH_INFINITE);
   }

Java 問題マーカーは、Java プロジェクト・ビルダーによって保守され、問題が解決されて Java ソースが再コンパイルされると、自動的に除去されます。

問題の ID 値は、 IProblem に定義されているいずれかの定数に設定されます。問題の ID は信頼性のあるものですが、メッセージはローカライズされ、デフォルト・ロケールに応じて変更されます。 IProblem に定義されている定数は自己記述です。

IProblemRequestor の実装は、Java 操作中に検出された問題を収集するように定義する必要があります。 作業用コピーの作成に IProblemRequestor が指定された場合、作業用コピーを問題検出と調整することができます。 これを行うには、reconcile メソッドを使用できます。以下に例を示します。

  ICompilationUnit unit = ..; // get some compilation unit
			
  // create requestor for accumulating discovered problems
  IProblemRequestor problemRequestor = new IProblemRequestor() {
    public void acceptProblem(IProblem problem) {
      System.out.println(problem.getID() + ": " + problem.getMessage());
    }
    public void beginReporting() {}
    public void endReporting() {}
    public boolean isActive() {	return true; } // will detect problems if active
  };
    
  // use working copy to hold source with error
  ICompilationUnit workingCopy = unit.getWorkingCopy(new WorkingCopyOwner() {}, problemRequestor, null);
  ((IOpenable)workingCopy).getBuffer().setContents("public class X extends Zork {}");

  // trigger reconciliation			
  workingCopy.reconcile(NO_AST, true, null, null);
acceptProblem(IProblem) メソッドで報告された問題について、アクションを追加することができます。 この例では、報告された問題は、Zork を解決できないか、または有効なスーパークラスではないということと、問題の ID が IProblem.SuperclassNotFound であるということです。

SuppressWarnings を使用しての警告の排除

Java 5.0 では、注釈 java.lang.SuppressWarning を使用して、コンパイル・ユニットのサブセットに関するコンパイル警告を使用できないようにするオプションをユーザーに提供しています。

	@SuppressWarning("unused") public void foo() {
		String s;
	}

注釈を使用しない場合、コンパイラーはローカル変数 s が使用されないことを指摘します。 注釈を使用する場合、コンパイラーは foo メソッドに対して、この警告をローカルに無視します。これにより、同じコンパイル・ユニットまたは同じプロジェクトのほかのロケーションで警告を保持できます。

SuppressWarning 注釈内で使用可能なトークンのリストは次のとおりです。