การคอมไพล์ด้วยแจ็ค (AOSP 6.0 - 8.1)

Jack เป็นชุดเครื่องมือเริ่มต้นของ Android build สำหรับ Android 6.0 - 8.1

Jack เป็น toolchain ของ Android ที่คอมไพล์ซอร์ส Java ลงใน Android dex bytecode คุณไม่จำเป็นต้องทำอะไรที่แตกต่างออกไปเพื่อใช้ Jack เพียงใช้คำสั่ง makefile มาตรฐานเพื่อคอมไพล์แผนผังหรือโปรเจ็กต์ของคุณ Android 8.1 เป็นรุ่นล่าสุดที่ใช้ Jack

เกี่ยวกับแจ็ค

แจ็คทำงานดังแสดงในรูปที่ 1

ภาพรวมของแจ็ค

รูปที่ 1. ภาพรวมของแจ็ค

รูปแบบไลบรารีแจ็ค

Jack มีรูปแบบไฟล์ .jack ของตัวเองซึ่งมีโค้ด dex ที่คอมไพล์ไว้ล่วงหน้าสำหรับไลบรารี ทำให้สามารถคอมไพล์ได้เร็วขึ้น (pre-dex)

เนื้อหาไฟล์ไลบรารีของแจ็ค

รูปที่ 2. เนื้อหาไฟล์ไลบรารีของแจ็ค

จิล

ดังแสดงในรูปต่อไปนี้ เครื่องมือ Jill จะแปลไลบรารี .jar ที่มีอยู่ให้เป็นรูปแบบไลบรารีใหม่

เวิร์กโฟลว์เพื่อนำเข้าไลบรารี `jar.` ที่มีอยู่

รูปที่ 3 เวิร์กโฟลว์เพื่อนำเข้าไลบรารี .jar ที่มีอยู่

เซิร์ฟเวอร์การคอมไพล์แจ็ค

ครั้งแรกที่ใช้แจ็ค จะเปิดตัวเซิร์ฟเวอร์การคอมไพล์แจ็คในเครื่องคอมพิวเตอร์ของคุณ เซิร์ฟเวอร์นี้:

  • นำมาซึ่งการเร่งความเร็วที่แท้จริงเนื่องจากจะหลีกเลี่ยงการเปิดตัวโฮสต์ใหม่ JRE JVM, กำลังโหลดโค้ด Jack, กำลังเตรียมใช้งาน Jack และอุ่นเครื่อง JIT ในแต่ละการคอมไพล์ นอกจากนี้ยังให้เวลาในการคอมไพล์ที่ดีมากในระหว่างการคอมไพล์ขนาดเล็ก (เช่น ในโหมดส่วนเพิ่ม)
  • เป็นวิธีแก้ปัญหาระยะสั้นในการควบคุมจำนวนการคอมไพล์แจ็คแบบขนาน เซิร์ฟเวอร์หลีกเลี่ยงการโอเวอร์โหลดคอมพิวเตอร์ของคุณ (ปัญหาหน่วยความจำหรือดิสก์) เนื่องจากจะจำกัดจำนวนการคอมไพล์แบบขนาน

เซิร์ฟเวอร์ Jack ปิดตัวเองลงหลังจากไม่ได้ใช้งานโดยไม่มีการคอมไพล์ใดๆ ใช้พอร์ต TCP สองพอร์ตบนอินเทอร์เฟซ localhost และไม่พร้อมใช้งานภายนอก พารามิเตอร์ทั้งหมด (จำนวนการคอมไพล์แบบขนาน การหมดเวลา หมายเลขพอร์ต ฯลฯ) สามารถแก้ไขได้โดยการแก้ไขไฟล์ $HOME/.jack

ไฟล์ $HOME/.jack

ไฟล์ $HOME/.jack มีการตั้งค่าต่อไปนี้สำหรับตัวแปรเซิร์ฟเวอร์ Jack ในรูปแบบทุบตีแบบเต็ม:

  • 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 พร้อมกันโดยแก้ไข $HOME/.jack และเปลี่ยน SERVER_NB_COMPILE เป็นค่าที่ต่ำกว่า
การคอมไพล์ล้มเหลวบน ไม่สามารถเปิดเซิร์ฟเวอร์พื้นหลังได้ สาเหตุที่เป็นไปได้มากที่สุดคือมีการใช้พอร์ต 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 )

การค้นหาบันทึกของแจ็ค

หากคุณรันคำสั่ง make ด้วยเป้าหมาย dist บันทึกของ Jack จะอยู่ที่ $ANDROID_BUILD_TOP/out/dist/logs/jack-server.log มิฉะนั้น คุณสามารถค้นหาบันทึกได้โดยการรัน jack-admin server-log ในกรณีที่แจ็คทำซ้ำได้ล้มเหลว คุณสามารถรับบันทึกที่มีรายละเอียดเพิ่มเติมได้โดยการตั้งค่าตัวแปรต่อไปนี้:

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 ในปัจจุบัน ไม่รองรับเครื่องมือจัดการ Bytecode (เช่น JaCoCo)

ใช้แจ็ค

Jack รองรับภาษาการเขียนโปรแกรม Java 1.7 และรวมคุณสมบัติเพิ่มเติมที่อธิบายไว้ด้านล่าง

การจัดทำดัชนีล่วงหน้า

เมื่อสร้างไฟล์ไลบรารี Jack .dex ของไลบรารีจะถูกสร้างขึ้นและจัดเก็บไว้ในไฟล์ไลบรารี .jack เป็น pre-dex เมื่อทำการคอมไพล์ Jack จะนำ pre-dex มาใช้ซ้ำจากแต่ละไลบรารี ไลบรารีทั้งหมดได้รับการจัดทำดัชนีไว้ล่วงหน้า

ไลบรารีแจ็คพร้อม pre-dex

รูปที่ 4 ไลบรารีของแจ็คที่มี pre-dex

แจ็คจะไม่นำไลบรารี pre-dex มาใช้ซ้ำหากใช้การย่อขนาด การสร้างความสับสน หรือการทำแพ็กเกจใหม่ในการคอมไพล์

การรวบรวมที่เพิ่มขึ้น

การคอมไพล์แบบเพิ่มหน่วยหมายความว่าเฉพาะคอมโพเนนต์ที่สัมผัสตั้งแต่การคอมไพล์ครั้งล่าสุด (และการขึ้นต่อกัน) เท่านั้นที่จะถูกคอมไพล์ใหม่ การคอมไพล์แบบเพิ่มหน่วยอาจเร็วกว่าการคอมไพล์แบบเต็มอย่างมาก เมื่อการเปลี่ยนแปลงถูกจำกัดอยู่เพียงชุดของส่วนประกอบ

การคอมไพล์ส่วนเพิ่มจะถูกปิดใช้งานตามค่าเริ่มต้น (และจะถูกปิดใช้งานโดยอัตโนมัติเมื่อเปิดใช้งานการย่อขนาด การสร้างความสับสน การบรรจุใหม่ หรือการใช้ multi-dex แบบเดิม) หากต้องการเปิดใช้งานบิลด์ส่วนเพิ่ม ให้เพิ่มบรรทัดต่อไปนี้ลงในไฟล์ Android.mk ของโปรเจ็กต์ที่คุณต้องการสร้างแบบส่วนเพิ่ม:

LOCAL_JACK_ENABLED := incremental

การหดตัวและการทำให้งงงวย

แจ็คใช้ไฟล์การกำหนดค่า ProGuard เพื่อเปิดใช้งานการย่อขนาดและทำให้สับสน

ตัวเลือกทั่วไปมีดังต่อไปนี้:

  • @
  • -include
  • -basedirectory
  • -injars
  • -outjars (รองรับโถเอาต์พุตเพียง 1 อันเท่านั้น)
  • -libraryjars
  • -keep
  • -keepclassmembers
  • -keepclasseswithmembers
  • -keepnames
  • -keepclassmembernames
  • -keepclasseswithmembernames
  • -printseeds

ตัวเลือกการย่อขนาดมีดังต่อไปนี้:

  • -dontshrink

ตัวเลือกการทำให้งงงวยมีดังต่อไปนี้:

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

ตัวเลือกที่ถูกละเว้นมีดังต่อไปนี้:

  • -dontoptimize (แจ็คไม่ปรับให้เหมาะสม)
  • -dontpreverify (แจ็คไม่ได้ยืนยันล่วงหน้า)
  • -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"

รองรับมัลติเดกซ์

Jack ให้การสนับสนุน multidex ในตัวและแบบเดิม เนื่องจากไฟล์ dex จำกัดอยู่ที่ 65K วิธี แอปที่มีมากกว่า 65K วิธีจึงต้องแบ่งออกเป็นไฟล์ dex หลายไฟล์ สำหรับรายละเอียดเพิ่มเติม โปรดดูที่ เปิดใช้งาน multidex สำหรับแอปที่มีวิธีการมากกว่า 64,000 วิธี