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

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

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

เกี่ยวกับ Jack

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

ภาพรวมของ Jack

รูปที่ 1 ภาพรวมของ Jack

รูปแบบไลบรารีของ 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 มีการตั้งค่าต่อไปนี้สำหรับตัวแปรเซิร์ฟเวอร์ 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 ล้มเหลวเนื่องจาก Out of memory error ลดจำนวนการคอมไพล์ของ 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 ด้วยเป้าหมาย 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 ในปัจจุบัน ระบบไม่รองรับเครื่องมือจัดการ bytecode (เช่น JaCoCo)

ใช้ Jack

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

Pre-dex

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

ไลบรารี Jack ที่มีกระบวนการแปลงเป็นไฟล์ .dex ล่วงหน้า

รูปที่ 4 ไลบรารีของ Jack ที่มี pre-dex

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

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

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

การคอมไพล์แบบเพิ่มจะปิดใช้โดยค่าเริ่มต้น (และจะปิดใช้งานโดยอัตโนมัติเมื่อเปิดใช้การลดขนาด การปรับให้ยากต่อการอ่าน การจัดแพ็กเกจใหม่ หรือ 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 เมธอด