คอมไพล์ด้วย Jack (AOSP 6.0 - 8.1)

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

Jack เป็น Toolchain ของ Android ที่คอมไพล์ซอร์ส Java เป็น Dex Bytecode ของ Android คุณไม่ต้องดําเนินการใดๆ เพิ่มเติมเพื่อใช้ Jack เพียงแค่ใช้คําสั่ง makefile มาตรฐานเพื่อคอมไพล์ต้นไม้หรือโปรเจ็กต์ Android 8.1 เป็นรุ่นล่าสุดที่ใช้ Jack

เกี่ยวกับ Jack

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

ภาพรวมของ Jack

รูปที่ 1 ภาพรวมของ 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 2 พอร์ตในอินเทอร์เฟซ 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 เป็นค่าที่ต่ำลง
การคอมไพล์ล้มเหลวในไม่สามารถเปิดเซิร์ฟเวอร์ที่ทำงานอยู่เบื้องหลัง สาเหตุที่เป็นไปได้มากที่สุดคือมีการใช้พอร์ต 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 ที่มีเป้าหมาย dist บันทึกของ 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

โดยค่าเริ่มต้น มีเพียงผู้ใช้รายเดียวในคอมพิวเตอร์ที่ใช้เซิร์ฟเวอร์ Jack ได้ หากต้องการรองรับผู้ใช้เพิ่มเติม ให้เลือกหมายเลขพอร์ตที่แตกต่างกันสำหรับผู้ใช้แต่ละรายและปรับ SERVER_NB_COMPILE ให้เหมาะสม นอกจากนี้ คุณยังปิดใช้เซิร์ฟเวอร์ Jack ได้โดยตั้งค่า SERVER=false ใน $HOME/.jack การคอมไพล์ CTS ช้าเนื่องจากการผสานรวม vm-tests-tf ปัจจุบัน ไม่รองรับเครื่องมือการจัดการไบต์โค้ด (เช่น JaCoCo)

ใช้ Jack

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

ก่อนแปลงเพศ

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

ไลบรารีของ Jack ที่มี Pre-dex

รูปที่ 4 ไลบรารี Jack ที่มี Pre-Dex

แจ็คไม่ได้ใช้ไฟล์ Pre-dex ของไลบรารีซ้ำหากมีการย่อ ปรับให้ยากต่อการอ่าน (Obfuscation) หรือการจัดแพ็กเกจใหม่ในการคอมไพล์

การคอมไพล์แบบเพิ่ม

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

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

LOCAL_JACK_ENABLED := incremental

การย่อโค้ดและการปรับให้ยากต่อการอ่าน

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

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

  • @
  • -include
  • -basedirectory
  • -injars
  • -outjars (รองรับ Jar เอาต์พุต 1 รายการเท่านั้น)
  • -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 จะใช้งานร่วมกับประเภทกฎ "rule" ได้ แต่จะใช้ร่วมกับประเภทกฎ "zap" หรือ "keep" ไม่ได้

การสนับสนุน Multidex

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