Jack は、Android 6.0~8.1 では、デフォルトの Android ビルド ツールチェーンです。
Jack は Java ソースを Android dex バイトコードにコンパイルする Android ツールチェーンです。Jack を使用するために特別なことをする必要はありません。標準の makefile コマンドを使用して、ツリーやプロジェクトをコンパイルできます。Jack を使用する最後のリリースは、Android 8.1 です。
Jack について
Jack は図 1 のように動作します。
図 1. Jack の概要
Jack ライブラリ形式
Jack は、独自の .jack ファイル形式を使用します。このファイルには、ライブラリ用にあらかじめコンパイルされた dex コードが格納されており、高速にコンパイルできます(pre-dex)。
図 2. Jack のライブラリ ファイルの内容
Jill
次の図に示すように、Jill ツールは既存の .jar ライブラリを新しいライブラリ形式に変換します。
図 3. 既存の .jar ライブラリをインポートするワークフロー
Jack コンパイル サーバー
初めて Jack を使用すると、コンピュータ上でローカル Jack コンパイル サーバーが起動します。このサーバーは次のような特長を備えています。
- 新しいホスト JRE JVM の起動や、Jack コードのロード、Jack の初期化、コンパイルごとの JIT のウォームアップを避けられるため、本質的な高速化が可能になります。また、増分モードなど、小規模なコンパイルの場合に、コンパイル時間を大幅に短縮できます。
- 並列 Jack コンパイルの数を制御できる短期的ソリューションです。このサーバーは、並列コンパイル数を制限するため、コンピュータ(メモリやディスク)への過負荷を避けることができます。
Jack サーバーは、コンパイル処理のないアイドル時間が続くと、自動でシャットダウンします。localhost インターフェース上で 2 つの TCP ポートを使用し、外部からは利用できません。$HOME/.jack ファイルを編集することで、すべてのパラメータ(並列コンパイル数、タイムアウト、ポート番号など)を編集できます。
$HOME/.jack ファイル
$HOME/.jack ファイルには、Jack サーバー変数に関する以下の設定が完全な bash 構文で指定されています。
SERVER=trueは、Jack のサーバー機能を有効にします。SERVER_PORT_SERVICE=8072は、コンパイル用のサーバー TCP ポート番号を設定します。SERVER_PORT_ADMIN=8073は、管理用のサーバー TCP ポート番号を設定します。SERVER_COUNT=1は、未使用です。SERVER_NB_COMPILE=4は、並列コンパイルの最大数を設定します。SERVER_TIMEOUT=60は、コンパイル処理のないアイドル状態になった後、サーバーが自動でシャットダウンするまで待機する秒数を設定します。SERVER_LOG=${SERVER_LOG:=$SERVER_DIR/jack-$SERVER_PORT_SERVICE.log}は、サーバーログを書き込むファイルを設定します。デフォルトでは、この変数は環境変数によってオーバーロードされます。JACK_VM_COMMAND=${JACK_VM_COMMAND:=java}は、ホスト上で JVM を起動する際に使用するデフォルト コマンドを設定します。デフォルトでは、この変数は環境変数によってオーバーロードされます。
Jack コンパイルに関するトラブルシューティング
| 問題 | アクション |
|---|---|
| コンパイル中にコンピュータが応答しなくなった、あるいは、メモリ不足によるエラーで Jack コンパイルが失敗する | $HOME/.jack を編集して SERVER_NB_COMPILE を低い値に変更することで、同時 Jack コンパイルの数を減らします。 |
| コンパイルに失敗し、バックグラウンド サーバーを起動できない | 最も可能性が高い原因として、コンピュータ上の TCP ポートがすでに使用されていることが考えられます。$HOME/.jack(SERVER_PORT_SERVICE 変数および SERVER_PORT_ADMIN 変数)を編集してポートを変更します。状況を打開するには、$HOME/.jack を編集して SERVER を false にすることで、Jack コンパイル サーバーを無効にします。これにより、残念ながらコンパイルが大幅に遅くなるため、負荷制御(make の -l オプション)を使用した make -j の起動が必要となる場合があります。 |
| コンパイルがスタックして進まない | 状況を打開するには、jack-admin kill-server を使用して Jack バックグラウンド サーバーを強制終了します。その後、ユーザーの一時ディレクトリ(/tmp または $TMPDIR)内の jack-$USER に含まれている一時ディレクトリを削除します。 |
Jack ログを見つける
dist ターゲットを指定して make コマンドを実行した場合、Jack ログは $ANDROID_BUILD_TOP/out/dist/logs/jack-server.log にあります。それ以外の場合は、jack-admin server-log を実行することで、ログを見つけることができます。Jack エラーが再現可能な場合、次の変数を設定すると、詳細なログを取得できます。
export ANDROID_JACK_EXTRA_ARGS="--verbose debug --sanity-checks on -D sched.runner=single-threaded"
標準の makefile コマンドを使用してツリー(またはプロジェクト)をコンパイルし、標準の出力とエラーをアタッチします。詳細なビルドログを削除するには、次のコマンドを実行します。
unset ANDROID_JACK_EXTRA_ARGS
Jack に関する制限
デフォルトでは、Jack サーバーを使用できるのは 1 台のコンピュータ上の 1 人のユーザーだけに限られます。ユーザーの追加をサポートするには、ユーザーごとに異なるポート番号を選択し、それに応じて SERVER_NB_COMPILE を調整します。また、$HOME/.jack 内で SERVER=false を設定することで、Jack サーバーを無効にできます。現在のところ、vm-tests-tf 統合により CTS コンパイルは低速です。バイトコード操作ツール(JaCoCo など)はサポートされていません。
Jack を使用する
Jack は Java プログラミング言語 1.7 をサポートしており、以下で説明する追加機能を備えています。
pre-dex をかける
Jack ライブラリ ファイルを生成すると、ライブラリの .dex が生成され、.jack ライブラリ ファイル内に pre-dex として保存されます。Jack は、コンパイル時に各ライブラリの pre-dex を再利用します。ライブラリはすべて pre-dex 変換されます。
図 4. pre-dex を格納する Jack ライブラリ
コンパイル時に圧縮や難読化、再パッケージ化を使用する場合、ライブラリ内の pre-dex は再利用されません。
増分コンパイル
増分コンパイルとは、前回コンパイルした後に変更されたコンポーネント(およびその依存関係)だけを再コンパイルすることです。変更の対象が一部のコンポーネント セットだけに限られる場合、増分コンパイルは、フルコンパイルに比べて大幅な高速化が可能です。
増分コンパイルは、デフォルトでは無効になっています。また、圧縮や難読化、再パッケージ化、旧式 multidex を有効にすると、自動的に無効化されます。増分ビルドを有効にするには、増分ビルドを行うプロジェクトの Android.mk ファイルに次の行を追加します。
LOCAL_JACK_ENABLED := incremental
圧縮と難読化
Jack は、ProGuard 構成ファイルを使用して、圧縮や難読化の有効化を行います。
一般的なオプションは次のとおりです。
@-include-basedirectory-injars-outjars(サポートされる出力 jar は 1 つのみ)-libraryjars-keep-keepclassmembers-keepclasseswithmembers-keepnames-keepclassmembernames-keepclasseswithmembernames-printseeds
圧縮には次のようなオプションがあります。
-dontshrink
難読化には次のようなオプションがあります。
-dontobfuscate-printmapping-applymapping-obfuscationdictionary-classobfuscationdictionary-packageobfuscationdictionary-useuniqueclassmembernames-dontusemixedcaseclassnames-keeppackagenames-flattenpackagehierarchy-repackageclasses-keepattributes-adaptclassstrings
以下のオプションは無視されます。
-dontoptimize(Jack は最適化を行いません)-dontpreverify(Jack は事前検証を行いません)-skipnonpubliclibraryclasses-dontskipnonpubliclibraryclasses-dontskipnonpubliclibraryclassmembers-keepdirectories-target-forceprocessing-printusage-whyareyoukeeping-optimizations-optimizationpasses-assumenosideeffects-allowaccessmodification-mergeinterfacesaggressively-overloadaggressively-microedition-verbose-dontnote-dontwarn-ignorewarnings-printconfiguration-dump
再パッケージ化
Jack は、jarjar 構成ファイルを使用して、再パッケージ化を行います。Jack は「rule」ルールタイプと互換性がありますが、「zap」ルールタイプや「keep」ルールタイプとは互換性がありません。
Multidex のサポート
Jack は組み込み式および従来の multidex をサポートしています。dex ファイルは 65K メソッドの制限があるため、65K メソッドを超えるアプリの場合、複数の dex ファイルに分割する必要があります。詳細については、64K を超えるメソッドを使用するアプリ向けに multidex を有効化するをご覧ください。