Biên dịch với Jack (AOSP 6.0 – 8.1)

Jack là chuỗi công cụ bản dựng Android mặc định cho Android 6.0 – 8.1

Jack là một chuỗi công cụ Android đã biên dịch nguồn Java thành mã byte Android dex. Bạn không cần làm gì khác để sử dụng Jack – chỉ cần sử dụng các lệnh makefile tiêu chuẩn để biên dịch cây hoặc dự án. Android 8.1 là bản phát hành cuối cùng sử dụng Jack.

Giới thiệu về Jack

Jack hoạt động như minh hoạ trong Hình 1.

Tổng quan về Jack.

Hình 1. Tổng quan về Jack.

Định dạng thư viện Jack

Jack có định dạng tệp .jack riêng chứa mã dex được biên dịch trước cho thư viện, cho phép biên dịch nhanh hơn (pre-dex).

Nội dung tệp thư viện Jack.

Hình 2. Nội dung tệp thư viện Jack.

Jill

Như minh hoạ trong hình sau, công cụ Jill dịch các thư viện .jar hiện có sang định dạng thư viện mới.

Quy trình nhập thư viện "jar" hiện có.

Hình 3. Quy trình làm việc để nhập thư viện .jar hiện có.

Máy chủ biên dịch giắc cắm

Lần đầu tiên sử dụng, Jack sẽ khởi chạy một máy chủ biên dịch Jack cục bộ trên máy tính của bạn. Máy chủ này:

  • Mang đến tốc độ nội tại vì nó tránh khởi chạy JRE JVM máy chủ mới, tải mã Jack, khởi chạy Jack và khởi động JIT ở mỗi lần biên dịch. Phương thức này cũng cung cấp thời gian biên dịch rất tốt trong các lần biên dịch nhỏ (ví dụ: ở chế độ gia tăng).
  • Là giải pháp ngắn hạn để kiểm soát số lượng bản biên dịch song song của Jack. Máy chủ tránh tình trạng máy tính quá tải (vấn đề về bộ nhớ hoặc ổ đĩa) vì máy chủ giới hạn số lượng bản biên dịch song song.

Máy chủ Jack tự tắt sau thời gian không hoạt động mà không có biên dịch nào. Giao thức này sử dụng hai cổng TCP trên giao diện localhost và không có sẵn bên ngoài. Bạn có thể sửa đổi tất cả các tham số (số lần biên dịch song song, thời gian chờ, số cổng, v.v.) bằng cách chỉnh sửa tệp $HOME/.jack.

Tệp $HOME/.jack

Tệp $HOME/.jack chứa các chế độ cài đặt sau cho biến máy chủ Jack trong cú pháp bash đầy đủ:

  • SERVER=true bật tính năng máy chủ của Jack.
  • SERVER_PORT_SERVICE=8072 đặt số cổng TCP của máy chủ cho mục đích biên dịch.
  • SERVER_PORT_ADMIN=8073 đặt số cổng TCP của máy chủ cho mục đích quản trị.
  • SERVER_COUNT=1 không được sử dụng.
  • SERVER_NB_COMPILE=4 đặt số lượng tối đa các bản biên dịch song song được phép. SERVER_TIMEOUT=60 đặt số giây không hoạt động mà máy chủ phải đợi mà không biên dịch trước khi tự tắt. SERVER_LOG=${SERVER_LOG:=$SERVER_DIR/jack-$SERVER_PORT_SERVICE.log} đặt tệp nơi ghi nhật ký máy chủ. Theo mặc định, một biến môi trường có thể nạp chồng biến này.
  • JACK_VM_COMMAND=${JACK_VM_COMMAND:=java} đặt lệnh mặc định dùng để khởi chạy JVM trên máy chủ. Theo mặc định, biến này có thể bị biến môi trường nạp chồng.

Khắc phục sự cố khi biên dịch Jack

Sự cố Thao tác
Máy tính của bạn không phản hồi trong quá trình biên dịch hoặc bạn gặp lỗi Hết bộ nhớ khi biên dịch Jack Giảm số lượng bản biên dịch đồng thời của Jack bằng cách chỉnh sửa $HOME/.jack và thay đổi SERVER_NB_COMPILE thành một giá trị thấp hơn.
Quá trình biên dịch không thành công trên Không thể chạy máy chủ trong nền Nguyên nhân có thể là các cổng TCP đã được sử dụng trên máy tính của bạn. Thay đổi cổng bằng cách chỉnh sửa $HOME/.jack (các biến SERVER_PORT_SERVICESERVER_PORT_ADMIN). Để bỏ chặn trường hợp này, hãy vô hiệu hoá máy chủ biên dịch Jack bằng cách chỉnh sửa $HOME/.jack và thay đổi SERVER thành false. Rất tiếc, điều này làm chậm đáng kể quá trình biên dịch và có thể buộc bạn phải chạy make -j bằng tính năng kiểm soát tải (tuỳ chọn -l của make).
Quá trình biên dịch bị treo mà không có tiến trình nào Để bỏ chặn tình huống này, hãy loại bỏ máy chủ nền Jack bằng jack-admin kill-server), sau đó xoá các thư mục tạm thời có trong jack-$USER của thư mục tạm thời (/tmp hoặc $TMPDIR).

Tìm nhật ký Jack

Nếu bạn chạy lệnh make có mục tiêu dist, thì nhật ký Jack sẽ nằm tại $ANDROID_BUILD_TOP/out/dist/logs/jack-server.log. Nếu không, bạn có thể tìm nhật ký bằng cách chạy jack-admin server-log. Trong trường hợp Jack gặp lỗi có thể tái hiện, bạn có thể xem nhật ký chi tiết hơn bằng cách đặt biến sau:

export ANDROID_JACK_EXTRA_ARGS="--verbose debug --sanity-checks on -D sched.runner=single-threaded"

Sử dụng các lệnh makefile tiêu chuẩn để biên dịch cây (hoặc dự án của bạn) và đính kèm đầu ra và lỗi tiêu chuẩn. Để xoá nhật ký bản dựng chi tiết, hãy chạy mã:

unset ANDROID_JACK_EXTRA_ARGS

Giới hạn về giắc cắm

Theo mặc định, chỉ một người dùng trên máy tính mới có thể sử dụng máy chủ Jack. Để hỗ trợ thêm người dùng, hãy chọn các số cổng khác nhau cho từng người dùng và điều chỉnh SERVER_NB_COMPILE cho phù hợp. Bạn cũng có thể tắt máy chủ Jack bằng cách đặt SERVER=false trong $HOME/.jack. Quá trình biên dịch CTS bị chậm do quá trình tích hợp vm-tests-tf hiện tại. Các công cụ thao tác mã byte (chẳng hạn như JaCoCo) không được hỗ trợ.

Sử dụng giắc cắm

Jack hỗ trợ ngôn ngữ lập trình Java 1.7 và tích hợp các tính năng bổ sung được mô tả dưới đây.

Pre-dex

Khi tạo tệp thư viện Jack, .dex của thư viện sẽ được tạo và lưu trữ bên trong tệp thư viện .jack dưới dạng tệp dex trước. Khi biên dịch, Jack sẽ sử dụng lại tệp dex trước từ mỗi thư viện. Tất cả thư viện đều được tạo sẵn tệp dex.

Thư viện Jack có pre-dex.

Hình 4. Thư viện Jack có pre-dex.

Jack không sử dụng lại thư viện trước khi tạo dex nếu quá trình thu nhỏ, làm rối mã nguồn hoặc đóng gói lại được sử dụng trong quá trình biên dịch.

Biên dịch gia tăng

Biên dịch gia tăng có nghĩa là chỉ các thành phần được chạm vào kể từ lần biên dịch gần đây nhất (và các phần phụ thuộc của các thành phần đó) được biên dịch lại. Việc biên dịch gia tăng có thể nhanh hơn đáng kể so với biên dịch đầy đủ khi các thay đổi bị giới hạn ở một nhóm thành phần.

Tính năng biên dịch gia tăng bị tắt theo mặc định (và tự động bị tắt khi rút gọn, làm rối mã nguồn, đóng gói lại hoặc bật tính năng cũ nhiều định dạng dex). Để bật bản dựng tăng dần, hãy thêm dòng sau vào tệp Android.mk của dự án mà bạn muốn tạo bản dựng tăng dần:

LOCAL_JACK_ENABLED := incremental

Thu hẹp và làm rối mã nguồn

Jack sử dụng tệp cấu hình ProGuard để bật tính năng rút gọn và làm rối mã nguồn.

Sau đây là các tuỳ chọn phổ biến:

  • @
  • -include
  • -basedirectory
  • -injars
  • -outjars (chỉ hỗ trợ 1 tệp đầu ra)
  • -libraryjars
  • -keep
  • -keepclassmembers
  • -keepclasseswithmembers
  • -keepnames
  • -keepclassmembernames
  • -keepclasseswithmembernames
  • -printseeds

Có các tuỳ chọn rút gọn sau:

  • -dontshrink

Có các tuỳ chọn làm rối mã nguồn sau:

  • -dontobfuscate
  • -printmapping
  • -applymapping
  • -obfuscationdictionary
  • -classobfuscationdictionary
  • -packageobfuscationdictionary
  • -useuniqueclassmembernames
  • -dontusemixedcaseclassnames
  • -keeppackagenames
  • -flattenpackagehierarchy
  • -repackageclasses
  • -keepattributes
  • -adaptclassstrings

Sau đây là các tuỳ chọn bị bỏ qua:

  • -dontoptimize (Jack không tối ưu hoá)
  • -dontpreverify (Jack không xác minh trước)
  • -skipnonpubliclibraryclasses
  • -dontskipnonpubliclibraryclasses
  • -dontskipnonpubliclibraryclassmembers
  • -keepdirectories
  • -target
  • -forceprocessing
  • -printusage
  • -whyareyoukeeping
  • -optimizations
  • -optimizationpasses
  • -assumenosideeffects
  • -allowaccessmodification
  • -mergeinterfacesaggressively
  • -overloadaggressively
  • -microedition
  • -verbose
  • -dontnote
  • -dontwarn
  • -ignorewarnings
  • -printconfiguration
  • -dump

Đóng gói lại

Jack sử dụng các tệp cấu hình jarjar để đóng gói lại. Mặc dù Jack tương thích với các loại quy tắc "quy tắc", nhưng Jack không tương thích với các loại quy tắc "zap" hoặc "keep".

Hỗ trợ Multidex

Jack cung cấp tính năng hỗ trợ multidex tích hợp và cũ. Vì tệp dex bị giới hạn ở các phương thức 65K, nên các ứng dụng có hơn 65K phương thức phải được chia thành nhiều tệp dex. Để biết thêm thông tin chi tiết, hãy tham khảo phần Bật multidex cho các ứng dụng có hơn 64K phương thức