Pluggable Annotation Processing APIとAndroid

今日のエントリは@vvakameさんのTwitterでの一連の呟きから閃いて書いた。

AndroidJava言語とその周辺の環境を利用して開発する。

Java言語は元々プリプロセッサを持たず、お世辞にもリッチとはいえないビルド環境※のお陰で、ランタイムに全ての処理を行うようにプログラミングしがちだ。それはAndroidでも変わらない(変わってくれると良かったのだが)

例えば、現在書いているライブラリィはどこにあるか解らないアクションクラスを前もって内部に登録するためにAndroidパッケージの内部を走査する。

public static void forEachDexFile(final DexFile dexFile) {
    final String targetPackage = handler.getContext().getPackageName();
    final Enumeration enumeration = dexFile.entries();
    
    while (enumeration.hasMoreElements()) {
        final String entry = enumeration.nextElement();
        if ( entry.startsWith(targetPackage)) {
           //対象のクラスがアクションクラスかを判定し、内部リポジトリに登録する
           //具体的にはメソッドに @Execute アノテーションが記述されているかどうか が判断基準になる
        }
    }
}  

この処理は起動時に必ず一度呼ばれるが、Dexパッケージ(classes.dex)中の全てのクラスを走査する上に、実行時にアノテーション、メソッド、クラスの情報をリフレクションを介して取得するため、当然ながら時間がかかる。パッケージ中のファイルが多ければ更に時間はかかるだろう。
サーバサイドであれば一度起動したアプリケーションはそのままヒープ上に乗っていることが殆どだが、クライアントそれもAndroidのようにリソースに制限のあるプラットホームの場合、アプリケーションは片っ端から消され、そのたびに再実行されるため(実際に再実行しているとは限らないのだが)甚だ非効率だ。また、起動時間が長いとそれだけでユーザからはそっぽを向かれる可能性もある。

一番良いのはプロジェクトをコンパイルした時に決定されているパッケージ中のクラスの走査、特定の条件にあったクラスかどうかの検査はコンパイル時にやってしまうことだ。そうすれば起動の度にパッケージを全て走査する処理は不要になる。

しかし冒頭に書いたようにJavaにはプリプロセッサは無い。
そこで表題のPluggable Annotation Processing APIの出番だ。

JSR 269: Pluggable Annotation Processing API
注釈処理ツール (apt) - java.sun.com

一般的な説明使い方は以下のサイトが分かり易い。というか私も全てこれを参考にさせて頂いた。

その他の機能Java SE 6 Mustang-TECHSCORE-
Eclipse で Pluggable Annotation Processing API - taediumの日記

Pluggable Annotation Processing APIとは、かいつまむとコンパイルタイム時に割り込んでソースコード上に記述された注釈(アノテーション)を処理するためのユーティリティクラス群を指す。JSDKの文書ではaptというアクロニム(Annotation Processing Tool?)と呼ぶので以降 aptと訳することにする。

重要なのはアノテーションを処理する = コンパイル時のJavaソースコードとその周辺にアクセスできることである。またCompile APIと組合わせることでソースコードを生成してコンパイルすることもてできる。aptによりJavaは一種のプリプロセッサを手に入れたともいえる。

このapt、Java5の際に既に導入されていたがその際はプロセッサの他にファクトリクラスが必要などコーディングが煩雑だった。Java6になったことでAPIが刷新され"Pluggable"になったことでIDE等開発環境との連携もしやすくなっている。

ということでこのaptをAndroidのプログラミングでもいろいろと生かせるのではないかと妄想したのだが、ここで大きな問題が二つある。

  • aptはJava6を要求する
  • aptはAndroidではサポートされていない

どちらもかなり致命的だが、少なくとも使うことだけは出来ることは確認できた。長くなったので具体的な使用例は次回に。


※そのおかげでApache Ant、Maven等の素晴らしいビルドツール、プロジェクト管理ツールが生まれた訳だ