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

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

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

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

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

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

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

ใช้ Jack

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

Pre-dex

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

ไลบรารี Jack ที่มี pre-dex

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

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

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

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

การคอมไพล์แบบเพิ่มจะปิดใช้โดยค่าเริ่มต้น (และจะปิดใช้งานโดยอัตโนมัติ เมื่อเปิดใช้การลดขนาด การปกปิด การบรรจุใหม่ หรือ Multi-Dex Legacy) หากต้องการเปิดใช้การบิลด์แบบเพิ่ม ให้เพิ่มบรรทัดต่อไปนี้ลงใน Android.mk ของโปรเจ็กต์ที่ต้องการบิลด์แบบเพิ่ม

LOCAL_JACK_ENABLED := incremental

การย่อและการปรับให้ยากต่อการอ่าน (Obfuscation)

แจ็คใช้ไฟล์การกำหนดค่า 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 (แจ็คไม่เพิ่มประสิทธิภาพ)
  • -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"

การรองรับ Multidex

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