Jack היה שרשרת הכלים לבנייה של Android כברירת מחדל ב-Android מגרסה 6.0 עד 8.1, והוא שימש לקומפילציה של קוד מקור של Java ל-bytecode של Android dex, כמו שמוצג באיור 1:
איור 1. סקירה כללית של ג'ק.
פורמט הקובץ .jack מכיל את קוד ה-dex שעבר הידור מראש עבור הספרייה, מה שמאפשר הידור מהיר יותר (pre-dex).
איור 2. תוכן קובץ הספרייה של Jack.
Jill tool
הכלי Jill מתרגם ספריות קיימות של .jar לפורמט החדש של ספריית .jack, כפי שמוצג באיור 3:
איור 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 בגלל אין זיכרון פנוי (OOM) | כדי לצמצם את מספר הקומפילציות של 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 ומשלב את התכונות הנוספות שמתוארות בקטע הזה. משתמשים בפקודות רגילות של makefile כדי לקמפל את העץ או את הפרויקט.
Pre-dex
כשיוצרים קובץ ספרייה של Jack, נוצר .dex של הספרייה והוא מאוחסן בתוך קובץ הספרייה .jack כ-pre-dex. במהלך הקומפילציה, Jack משתמש מחדש ב-pre-dex מכל ספרייה. כל הספריות עוברות המרה ל-Dex.
איור 4. ספריות Jack עם קובץ pre-dex.
ג'ק לא משתמש מחדש בספרייה לפני dex אם נעשה שימוש בהקטנה, בהסתרה או באריזה מחדש בהידור.
קומפילציה מצטברת
קומפילציה מצטברת פירושה שרק הרכיבים שהשתנו מאז הקומפילציה האחרונה (והתלויות שלהם) עוברים קומפילציה מחדש. קומפילציה מצטברת יכולה להיות מהירה משמעותית מקומפילציה מלאה, אם השינויים מוגבלים לקבוצה של רכיבים.
ההידור המצטבר מושבת כברירת מחדל (והוא מושבת אוטומטית אם מופעלת האפשרות 'הקטנה', 'הסתרה', 'אריזה מחדש' או 'multi-dex מדור קודם'). כדי להפעיל גרסאות build מצטברות, מוסיפים את השורה הבאה לקובץ Android.mk של הפרויקט שרוצים ליצור לו גרסאות build מצטברות:
LOCAL_JACK_ENABLED := incremental
כיווץ וערפול קוד (obfuscation)
ג'ק משתמש בקובצי תצורה של 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(ג'ק לא מבצע אימות מראש) -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 אלף שיטות, ולכן אפליקציות עם יותר מ-65 אלף שיטות צריכות להיות מחולקות למספר קובצי dex. מידע נוסף מופיע במאמר הפעלת multidex באפליקציות עם יותר מ-64, 000 שיטות.