Jack 是 Android 6.0 至 8.1 的預設 Android 建構工具鍊
Jack 是 Android 工具鍊,可將 Java 來源編譯為 Android dex 位元碼。使用 Jack 時,您不必採取任何其他行動,只要使用標準的 makefile 指令編譯樹狀結構或專案即可。Android 8.1 是最後一個使用 Jack 的版本。
關於 Jack
插孔的運作方式如圖 1 所示。
圖 1. Jack 總覽。
Jack 程式庫格式
Jack 有自己的 .jack
檔案格式,其中包含程式庫的預先編譯 dex 程式碼,可加快編譯速度 (預先 dex)。
圖 2. Jack 程式庫檔案內容。
Jill
如下圖所示,Jill 工具會將現有的 .jar
程式庫轉換為新的程式庫格式。
圖 3. 匯入現有 .jar
程式庫的工作流程。
Jack 編譯伺服器
首次使用 Jack 時,系統會在電腦上啟動本機 Jack 編譯伺服器。這個伺服器:
- 可避免在每次編譯時啟動新的主機 JRE JVM、載入 Jack 程式碼、初始化 Jack,以及預熱 JIT,因此可大幅提升速度。此外,在小型編譯期間 (例如在累加模式下),編譯時間也相當短。
- 這是短期解決方案,可控制平行 Jack 編譯的數量。伺服器會限制平行編譯的數量,避免電腦過載 (記憶體或磁碟問題)。
如果閒置一段時間後沒有任何編譯作業,Jack 伺服器就會自行關閉。
這個介面會使用本機介面上的兩個 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 編譯問題
問題 | 動作 |
---|---|
編譯期間電腦沒有回應,或發生 Out of memory 錯誤,導致 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 記錄
如果您使用發布目標執行 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 伺服器。如要支援其他使用者,請為每位使用者選取不同的通訊埠號碼,並相應調整 SERVER_NB_COMPILE
。您也可以在 $HOME/.jack
中設定 SERVER=false
,停用 Jack 伺服器。由於目前的 vm-tests-tf
整合,CTS 編譯速度緩慢。
不支援位元碼操控工具 (例如 JaCoCo)。
使用 Jack
Jack 支援 Java 程式設計語言 1.7,並整合下列其他功能。
Pre-dex
產生 Jack 程式庫檔案時,系統會產生程式庫的 .dex
,並以 DEX 前置處理的形式儲存在 .jack
程式庫檔案中。編譯時,Jack 會重複使用每個程式庫的 DEX 前置處理。所有程式庫都已預先 dex 化。
圖 4. 使用預先 Dex 處理的 Jack 程式庫。
如果編譯時使用縮減、模糊處理或重新封裝,Jack 就不會重複使用程式庫的預先 Dex 檔案。
增量編譯
增量編譯是指只重新編譯上次編譯後變更的元件 (及其依附元件)。如果變更僅限於一組元件,增量編譯的速度會比完整編譯快上許多。
增量編譯功能預設為停用 (啟用縮減、混淆、重新封裝或多重 DEX 舊版功能時,系統會自動停用這項功能)。如要啟用累加建構作業,請在要累加建構的專案 Android.mk
檔案中加入以下程式碼:
LOCAL_JACK_ENABLED := incremental
縮減和模糊處理
Jack 會使用 ProGuard 設定檔啟用縮減和模糊處理功能。
常見選項包括:
@
-include
-basedirectory
-injars
-outjars
(僅支援 1 個輸出 JAR)-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 支援「規則」規則類型,但不支援「Zap」或「保留」規則類型。
支援 Multidex
Jack 提供內建和舊版 multidex 支援。由於 dex 檔案最多只能有 65,000 個方法,因此如果應用程式的方法超過 65,000 個,就必須分割成多個 dex 檔案。詳情請參閱「針對使用超過 64K 方法的應用程式啟用 Multidex」