הידור עם Jack (AOSP 6.0 עד 8.1)

‫Jack הוא שרשרת הכלים לבניית Android שמוגדרת כברירת מחדל ב-Android 6.0 עד Android 8.1

‫Jack הוא שרשרת כלים של Android שהידרה קוד מקור של Java ל-bytecode של Android dex. כדי להשתמש ב-Jack, לא צריך לעשות שום דבר שונה – פשוט משתמשים בפקודות הרגילות של makefile כדי לקמפל את העץ או את הפרויקט. ‫Android 8.1 היא הגרסה האחרונה שמשתמשת ב-Jack.

מידע על ג'ק

החיבורים של שקע הטעינה מוצגים באיור 1.

סקירה כללית של ג'ק.

איור 1. סקירה כללית של ג'ק.

פורמט של ספריית Jack

ל-Jack יש .jack פורמט קובץ משלו שמכיל את קוד ה-dex שעבר קומפילציה מראש עבור הספרייה, וכך מאפשר קומפילציה מהירה יותר (pre-dex).

תוכן קובץ הספרייה של Jack.

איור 2. תוכן קובץ הספרייה של Jack.

Jill

כפי שמוצג באיור הבא, הכלי Jill מתרגם את הספריות הקיימות .jar לפורמט החדש של הספריות.

תהליך עבודה לייבוא ספריית jar.קיימת.

איור 3. תהליך עבודה לייבוא ספריית .jar קיימת.

שרת קומפילציה של Jack

בפעם הראשונה שמשתמשים ב-Jack, הוא מפעיל שרת הידור מקומי של Jack במחשב. השרת הזה:

  • הוא מביא לשיפור מהירות מובנה כי הוא מונע הפעלה של JRE JVM חדש במארח, טעינה של קוד Jack, הפעלה של Jack וחימום של JIT בכל קומפילציה. בנוסף, הוא מספק זמני קומפילציה טובים מאוד במהלך קומפילציות קטנות (לדוגמה, במצב מצטבר).
  • זהו פתרון לטווח קצר לשליטה במספר ההידור של Jack במקביל. השרת מונע עומס יתר על המחשב (בעיה בזיכרון או בדיסק) כי הוא מגביל את מספר ההידור המקבילי.

שרת Jack נסגר אחרי זמן השהיה ללא קומפילציה. הוא משתמש בשתי יציאות TCP בממשק localhost ולא זמין חיצונית. אפשר לשנות את כל הפרמטרים (מספר הקומפילציות המקבילות, הזמן הקצוב לתפוגה, מספר היציאות וכו') על ידי עריכה של הקובץ $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 כדי לצמצם את מספר ההידור בו-זמנית של קובצי Jack, עורכים את $HOME/.jack ומשנים את SERVER_NB_COMPILE לערך נמוך יותר.
הקומפילציות נכשלות בגלל השגיאה Cannot launch background server (אי אפשר להפעיל שרת ברקע) הסיבה הסבירה ביותר היא שיציאות TCP כבר נמצאות בשימוש במחשב. שינוי של יציאות על ידי עריכה של $HOME/.jack (המשתנים SERVER_PORT_SERVICE ו-SERVER_PORT_ADMIN). כדי לבטל את החסימה, משביתים את שרת הקומפילציה של Jack. לשם כך, עורכים את $HOME/.jack ומשנים את SERVER ל-false. לצערנו, זה מאט באופן משמעותי את ההידור שלכם ועשוי לחייב אתכם להפעיל את make -j עם בקרת טעינה (אפשרות -l מתוך make).
הקומפילציה נתקעת בלי להתקדם כדי לבטל את החסימה, צריך להרוג את שרת הרקע של Jack באמצעות jack-admin kill-server) ואז להסיר את הספריות הזמניות שנמצאות ב-jack-$USER של הספרייה הזמנית (/tmp או $TMPDIR).

איפה נמצא יומן 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 בהתאם. אפשר גם להשבית את שרת Jack על ידי הגדרת SERVER=false ב-$HOME/.jack. הקומפילציה של CTS איטית בגלל השילוב הנוכחי של vm-tests-tf. אין תמיכה בכלי מניפולציה של קוד בייט (כמו JaCoCo).

שימוש ב-Jack

‫Jack תומך בשפת התכנות Java 1.7 ומשלב את התכונות הנוספות שמתוארות בהמשך.

Pre-dex

כשיוצרים קובץ ספרייה של Jack, ה-.dex של הספרייה נוצר ונשמר בתוך קובץ הספרייה .jack כ-pre-dex. במהלך הקומפילציה, Jack משתמש מחדש ב-dex מראש מכל ספרייה. כל הספריות עוברות pre-dexing.

ספריות Jack עם pre-dex.

איור 4. ספריות Jack עם pre-dex.

אם משתמשים בהקטנה, בהסתרת קוד או באריזה מחדש בהידור, Jack לא משתמש מחדש בספרייה לפני ה-dex.

קומפילציה מצטברת

קומפילציה מצטברת פירושה שרק הרכיבים שהשתנו מאז הקומפילציה האחרונה (והתלויות שלהם) עוברים קומפילציה מחדש. קומפילציה מצטברת יכולה להיות מהירה משמעותית מקומפילציה מלאה, אם השינויים מוגבלים לקבוצת רכיבים.

הקומפילציה המצטברת מושבתת כברירת מחדל (והיא מושבתת אוטומטית כשמופעלת הקטנה, ההסתרה, האריזה מחדש או multi-dex מדור קודם). כדי להפעיל בנייה מצטברת, מוסיפים את השורה הבאה לקובץ Android.mk של הפרויקט שרוצים לבנות באופן מצטבר:

LOCAL_JACK_ENABLED := incremental

כיווץ וערפול קוד (obfuscation)

ג&#39ק משתמש בקובצי תצורה של ProGuard כדי להפעיל כיווץ והסתרה.

אלה כמה מהאפשרויות הנפוצות:

  • @
  • -include
  • -basedirectory
  • -injars
  • -outjars (יש תמיכה רק בקובץ 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 doesn't optimize)
  • -dontpreverify (Jack לא מבצע אימות מראש)
  • -skipnonpubliclibraryclasses
  • -dontskipnonpubliclibraryclasses
  • -dontskipnonpubliclibraryclassmembers
  • -keepdirectories
  • -target
  • -forceprocessing
  • -printusage
  • -whyareyoukeeping
  • -optimizations
  • -optimizationpasses
  • -assumenosideeffects
  • -allowaccessmodification
  • -mergeinterfacesaggressively
  • -overloadaggressively
  • -microedition
  • -verbose
  • -dontnote
  • -dontwarn
  • -ignorewarnings
  • -printconfiguration
  • -dump

אריזה מחדש

ג'ק משתמש בקובצי תצורה של jarjar כדי לבצע אריזה מחדש. ‫Jack תואם לסוגי כללים מסוג rule, אבל לא לסוגי כללים מסוג zap או keep.

תמיכה ב-multidex

‫Jack מציע תמיכה מובנית וגם תמיכה מדור קודם ב-multidex. מכיוון שקובצי dex מוגבלים ל-65,000 שיטות, אפליקציות עם יותר מ-65,000 שיטות צריכות להיות מחולקות למספר קובצי dex. לפרטים נוספים, אפשר לעיין במאמר הפעלת multidex באפליקציות עם יותר מ-64,000 שיטות