Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

Android 6.0~8.1 での Jack を使用したコンパイル

Jack は Java ソースを Android dex バイトコードにコンパイルする Android ツールチェーンです。Jack を使用するために特別なことをする必要はありません。標準の makefile コマンドを使用して、ツリーやプロジェクトをコンパイルできます。Jack を使用する最後のリリースは、Android 8.1 です。

Jack について

Jack は図 1 のように動作します。

Jack の概要
図 1: Jack の概要

Jack ライブラリ形式

Jack は、独自の .jack ファイル形式を使用します。このファイルには、ライブラリ用にあらかじめコンパイルされた dex コードが格納されており、高速にコンパイルできます(pre-dex)。

Jack ライブラリ ファイルの内容
図 2: Jack のライブラリ ファイルの内容

Jill

Jill ツールは、以下のように、既存の .jar ライブラリを新しいライブラリ形式に変換します。

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/.jackSERVER_PORT_SERVICE 変数および SERVER_PORT_ADMIN 変数)を編集してポートを変更します。状況を打開するには、$HOME/.jack を編集して SERVERfalse にすることで、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 変換されます。

pre-dex を格納する Jack ライブラリ
図 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 を有効化するをご覧ください。