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

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

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

เกี่ยวกับ Jack

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

ภาพรวมของ Jack

รูปที่ 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 2 พอร์ตในอินเทอร์เฟซ localhost และไม่สามารถเข้าถึงจากภายนอกได้ คุณแก้ไขพารามิเตอร์ทั้งหมด (จํานวนการคอมไพล์แบบขนาน ระยะหมดเวลา จํานวนพอร์ต ฯลฯ) ได้โดยแก้ไขไฟล์ $HOME/.jack

ไฟล์ $HOME/.jack

ไฟล์ $HOME/.jack มีการตั้งค่าต่อไปนี้สําหรับตัวแปร Jackbot Server ในไวยากรณ์ 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 และผสานรวมฟีเจอร์เพิ่มเติมที่อธิบายไว้ด้านล่าง

ไฟล์ .dex เวอร์ชันก่อนการคอมไพล์

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

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

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

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

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

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

การคอมไพล์แบบเพิ่มจะปิดอยู่โดยค่าเริ่มต้น (และจะปิดใช้งานโดยอัตโนมัติเมื่อเปิดใช้การบีบอัด การสร้างความสับสน การจัดแพ็กเกจใหม่ หรือ MultiDex รุ่นเดิม) หากต้องการเปิดใช้การสร้างแบบเพิ่ม ให้เพิ่มบรรทัดต่อไปนี้ลงในไฟล์ 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 รายการ