การตรวจสอบ Dexpreopt และ <uses-library>

Android 12 มีการเปลี่ยนแปลงระบบบิลด์ในการคอมไพล์ AOT ของไฟล์ DEX (dexpreopt) สำหรับโมดูล Java ที่มี <uses-library> ทรัพยากร Dependency ในบางกรณี การเปลี่ยนแปลงระบบบิลด์เหล่านี้อาจทำให้เสียหายได้ งานสร้าง ใช้หน้านี้เพื่อเตรียมรับมือการหยุดทำงาน และทำตามสูตรอาหารในนี้ หน้าเพื่อแก้ไขและบรรเทาปัญหา

Dexpreopt คือกระบวนการคอมไพล์ไลบรารีและแอป Java ล่วงหน้า Dexpreopt จะเกิดขึ้นในโฮสต์ในเวลาบิลด์ (ต่างจาก dexopt ซึ่ง เกิดขึ้นในอุปกรณ์) โครงสร้างของทรัพยากร Dependency ของไลบรารีที่ใช้ร่วมกันซึ่งโมดูล Java (ไลบรารีหรือแอป) ใช้เรียกว่าบริบทตัวโหลดคลาส (CLC) CLC ของช่วงสร้างและช่วงรันไทม์ต้องตรงกันเพื่อรับประกันความถูกต้องของ dexpreopt CLC ขณะสร้างคือสิ่งที่คอมไพเลอร์ dex2oat ใช้ ณ เวลา dexpreopt (บันทึกไว้ในไฟล์ ODEX) และ CLC ขณะรันไทม์คือบริบทที่โหลดโค้ดที่คอมไพล์ไว้ล่วงหน้าในอุปกรณ์

CLC เวลาที่บิลด์และรันไทม์เหล่านี้ต้องสอดคล้องกันด้วยเหตุผลทั้ง 2 อย่างเกี่ยวกับความถูกต้อง และประสิทธิภาพ เพื่อความถูกต้อง โปรดจัดการชั้นเรียนที่ซ้ำกัน ถ้า ทรัพยากร Dependency ของไลบรารีที่ใช้ร่วมกันขณะรันไทม์จะแตกต่างจากทรัพยากร Dependency ของไลบรารีที่ใช้ร่วมกัน เมื่อทำการรวมแล้ว บางชั้นเรียนอาจได้รับการแก้ไขต่างออกไป ซึ่งทำให้เกิดเป็นปัญหาเล็กน้อย ข้อบกพร่องรันไทม์ การตรวจสอบรันไทม์ยังมีผลต่อประสิทธิภาพการทำงานอีกด้วย ใหม่

กรณีการใช้งานที่ได้รับผลกระทบ

การบูตครั้งแรกเป็น Use Case หลักที่ได้รับผลกระทบจากการเปลี่ยนแปลงเหล่านี้: หาก ART ตรวจพบความไม่ตรงกันระหว่าง CLC ของช่วงสร้างและช่วงรันไทม์ ระบบจะปฏิเสธอาร์ติแฟกต์ dexpreopt และเรียกใช้ dexopt แทน สำหรับการบูตครั้งต่อๆ ไป สามารถทำได้เนื่องจาก สามารถถอดรหัสแอปในเบื้องหลังและจัดเก็บไว้ในดิสก์ได้

พื้นที่ที่ได้รับผลกระทบของ Android

ซึ่งจะส่งผลต่อแอปและไลบรารี Java ทั้งหมดที่ต้องใช้ไลบรารี Java อื่นๆ ในรันไทม์ Android มีแอปหลายพันแอป และหลายร้อยแอปใช้ไลบรารีที่แชร์ พาร์ทเนอร์ก็ได้รับผลกระทบด้วย เนื่องจากมีพาร์ทเนอร์ที่มีคลังและแอปของตนเอง

การเปลี่ยนแปลงช่วงพัก

ระบบของบิลด์จำเป็นต้องทราบทรัพยากร Dependency <uses-library> ก่อน สร้างกฎการสร้าง dexpreopt แต่จะเข้าถึงไฟล์ Manifest โดยตรงไม่ได้ และอ่าน <uses-library> แท็กในโค้ด เพราะระบบไม่อนุญาตให้อ่านไฟล์ที่กำหนดเองเมื่อ จะมีการสร้างกฎ (เพื่อเหตุผลด้านประสิทธิภาพ) นอกจากนี้ ไฟล์ Manifest อาจรวมอยู่ใน APK หรือไฟล์ที่สร้างไว้ล่วงหน้า ดังนั้น <uses-library> ต้องอยู่ในไฟล์บิลด์ (Android.bp หรือ Android.mk)

ก่อนหน้านี้ ART ใช้วิธีแก้ปัญหาชั่วคราวที่ไม่สนใจทรัพยากร Dependency ของไลบรารีที่ใช้ร่วมกัน (รู้จัก เป็น &-classpath) ค่านี้ไม่ปลอดภัยและทำให้เกิดข้อบกพร่องเล็กๆ น้อยๆ ดังนั้นการแก้ไขปัญหาเบื้องต้น ถูกนำออกจาก Android 12

ด้วยเหตุนี้ โมดูล Java ที่ไม่ได้ให้<uses-library>ข้อมูลในไฟล์บิลด์ที่ถูกต้องอาจทําให้การบิลด์ใช้งานไม่ได้ (เกิดจาก CLC ที่ไม่ตรงกันขณะสร้าง) หรือเวลาในการบูตครั้งแรกแย่ลง (เกิดจาก CLC ที่ไม่ตรงกันขณะบูตตามด้วย dexopt)

เส้นทางการย้ายข้อมูล

ทำตามขั้นตอนต่อไปนี้เพื่อแก้ไขบิลด์ที่เสียหาย

  1. ปิดใช้การตรวจสอบเวลาสร้างสำหรับผลิตภัณฑ์ที่เฉพาะเจาะจงทั่วโลกโดยการตั้งค่า

    PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true

    ในไฟล์ Make ของผลิตภัณฑ์ วิธีนี้จะแก้ไขข้อผิดพลาดในการสร้าง (ยกเว้นกรณีพิเศษ ที่แสดงในส่วนการแก้ไขข้อผิดพลาด) อย่างไรก็ตาม วิธีนี้เป็นวิธีแก้ปัญหาชั่วคราวและอาจทําให้ CLC ที่ไม่ตรงกันในเวลาบูตตามด้วย dexopt

  2. แก้ไขโมดูลที่ล้มเหลวก่อนที่คุณจะปิดใช้การตรวจสอบเวลาของบิลด์ทั่วโลก โดยเพิ่ม<uses-library>ข้อมูลที่จำเป็น ลงในไฟล์บิลด์ (ดูรายละเอียดในการแก้ไขข้อผิดพลาด) สำหรับโมดูลส่วนใหญ่ ต้องเพิ่ม 2-3 บรรทัดใน Android.bp หรือใน Android.mk

  3. ปิดใช้การตรวจสอบเวลาสร้างและ dexpreopt สำหรับกรณีที่มีปัญหา โดยแยกเป็นโมดูล ปิดใช้ Dexpreopt เพื่อไม่ให้เสียเวลาไปกับการสร้างและ พื้นที่เก็บข้อมูลบนอาร์ติแฟกต์ที่ถูกปฏิเสธเมื่อเปิดเครื่อง

  4. เปิดใช้การตรวจสอบเวลาสร้างอีกครั้งโดยยกเลิกการตั้งค่า PRODUCT_BROKEN_VERIFY_USES_LIBRARIES ที่ตั้งไว้ในขั้นตอนที่ 1 การสร้างไม่ควรล้มเหลวหลังจากการเปลี่ยนแปลงนี้ (เนื่องจากขั้นตอนที่ 2 และ 3)

  5. แก้ไขแต่ละข้อบังคับที่คุณปิดใช้ในขั้นตอนที่ 3 แล้วเปิดใช้ مجدد dexpreopt และการตรวจสอบ <uses-library> รายงานข้อบกพร่องหากจำเป็น

ระบบจะบังคับใช้การตรวจสอบ <uses-library> ขณะสร้างใน Android 12

แก้ไขการหยุดทำงาน

ส่วนต่อไปนี้จะแสดงวิธีแก้ไขการหยุดทำงานบางประเภท

ข้อผิดพลาดของบิลด์: CLC ไม่ตรงกัน

ระบบบิลด์จะตรวจสอบความสอดคล้องเวลาบิลด์ระหว่างข้อมูลใน Android.bp หรือ Android.mk และไฟล์ Manifest ระบบบิลด์ไม่สามารถอ่าน ไฟล์ Manifest แต่สามารถสร้างกฎการสร้างเพื่ออ่านไฟล์ Manifest (การดึงข้อมูล จาก APK หากจำเป็น) และเปรียบเทียบแท็ก <uses-library> ในไฟล์ Manifest กับข้อมูล <uses-library> ในไฟล์บิลด์ หากการตรวจสอบไม่สำเร็จ ข้อผิดพลาดจะมีลักษณะดังนี้

error: mismatch in the <uses-library> tags between the build system and the manifest:
    - required libraries in build system: []
                     vs. in the manifest: [org.apache.http.legacy]
    - optional libraries in build system: []
                     vs. in the manifest: [com.x.y.z]
    - tags in the manifest (.../X_intermediates/manifest/AndroidManifest.xml):
        <uses-library android:name="com.x.y.z"/>
        <uses-library android:name="org.apache.http.legacy"/>

note: the following options are available:
    - to temporarily disable the check on command line, rebuild with RELAX_USES_LIBRARY_CHECK=true (this will set compiler filter "verify" and disable AOT-compilation in dexpreopt)
    - to temporarily disable the check for the whole product, set PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true in the product makefiles
    - to fix the check, make build system properties coherent with the manifest
    - see build/make/Changes.md for details

ดังที่ข้อความแสดงข้อผิดพลาดแนะนำ มีวิธีแก้ปัญหาหลายวิธี ขึ้นอยู่กับ ความเร่งด่วน:

  • สำหรับการแก้ไขชั่วคราวทั่วทั้งผลิตภัณฑ์ ให้ตั้งค่า PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true ในไฟล์ยี่ห้อผลิตภัณฑ์ ระบบจะยังคงตรวจสอบความสอดคล้องกันของเวลาสร้าง แต่การตรวจสอบไม่สําเร็จไม่ได้หมายความว่าการสร้างไม่สําเร็จ แต่การตรวจสอบล้มเหลวจะทำให้ระบบบิลด์ดาวน์เกรด ตัวกรองคอมไพเลอร์ dex2oat เป็น verify ใน dexpreopt ซึ่งจะปิดใช้การคอมไพล์ AOT ทั้งหมดสำหรับโมดูลนี้
  • หากต้องการการแก้ไขแบบด่วนในบรรทัดคำสั่งแบบทั่วเว็บไซต์ ให้ใช้ตัวแปรสภาพแวดล้อม RELAX_USES_LIBRARY_CHECK=true ซึ่งให้ผลเช่นเดียวกับ PRODUCT_BROKEN_VERIFY_USES_LIBRARIES แต่มีจุดประสงค์เพื่อใช้ในบรรทัดคำสั่ง ตัวแปรสภาพแวดล้อมจะลบล้างตัวแปรผลิตภัณฑ์
  • หากต้องการวิธีแก้ไขที่ต้นเหตุของข้อผิดพลาด ให้แจ้งให้ระบบบิลด์ทราบถึงแท็ก <uses-library> ในไฟล์ Manifest การตรวจสอบข้อความแสดงข้อผิดพลาด จะแสดงไลบรารีที่ทำให้เกิดปัญหา (รวมถึงการตรวจสอบ AndroidManifest.xml หรือไฟล์ Manifest ภายใน APK ที่ตรวจสอบได้ กับ "aapt dump badging $APK | grep uses-library")

สำหรับโมดูล Android.bp ให้ทำดังนี้

  1. มองหาไลบรารีที่ขาดหายไปในพร็อพเพอร์ตี้ libs ของโมดูล หากเป็น ตามปกติ Soong จะเพิ่มไลบรารีดังกล่าวโดยอัตโนมัติ ยกเว้นใน กรณีพิเศษ:

    • ไลบรารีไม่ใช่ไลบรารี SDK (มีการกําหนดเป็น java_library ไม่ใช่ java_sdk_library)
    • ไลบรารีมีชื่อไลบรารี (ในไฟล์ Manifest) แตกต่างจากชื่อโมดูล (ในระบบบิลด์)

    หากต้องการแก้ไขปัญหานี้ชั่วคราว ให้เพิ่ม provides_uses_lib: "<library-name>" ใน คำจำกัดความของไลบรารี Android.bp หากต้องการแก้ปัญหาในระยะยาว ให้แก้ไขปัญหาพื้นฐาน เช่น แปลงไลบรารีเป็นไลบรารี SDK หรือเปลี่ยนชื่อโมดูล

  2. หากขั้นตอนก่อนหน้าไม่ได้ระบุวิธีแก้ปัญหา ให้เพิ่ม uses_libs: ["<library-module-name>"] สำหรับไลบรารีที่จำเป็น หรือ optional_uses_libs: ["<library-module-name>"] สำหรับไลบรารีที่ไม่บังคับเพื่อ คำจำกัดความ Android.bp ของโมดูลนี้ พร็อพเพอร์ตี้เหล่านี้ยอมรับรายการ ของชื่อโมดูล ลำดับสัมพัทธ์ของคลังในรายการต้องเหมือนกับลำดับในไฟล์ Manifest

สำหรับโมดูล Android.mk:

  1. ตรวจสอบว่าไลบรารีมีชื่อไลบรารีอื่น (ในไฟล์ Manifest) แตกต่างจาก ชื่อโมดูล (ในระบบบิลด์) หากปัญหายังคงอยู่ ให้แก้ไขปัญหานี้ชั่วคราวด้วยการเพิ่ม LOCAL_PROVIDES_USES_LIBRARY := <library-name> ในไฟล์ Android.mk ของ ไลบรารี หรือเพิ่ม provides_uses_lib: "<library-name>" ในAndroid.bp ของไลบรารี (ทั้ง 2 กรณีสามารถทำได้ตั้งแต่โมดูล Android.mk อาจขึ้นอยู่กับไลบรารี Android.bp) สำหรับการแก้ปัญหาในระยะยาว ให้แก้ไขปัญหาพื้นฐานซึ่งก็คือเปลี่ยนชื่อโมดูลไลบรารี

  2. เพิ่ม LOCAL_USES_LIBRARIES := <library-module-name> สำหรับไลบรารีที่ต้องระบุ และเพิ่ม LOCAL_OPTIONAL_USES_LIBRARIES := <library-module-name> สำหรับไลบรารีที่ไม่บังคับลงในคําจํากัดความ Android.mk ของข้อบังคับ พร็อพเพอร์ตี้เหล่านี้ยอมรับรายการชื่อโมดูล ลำดับแบบสัมพัทธ์ของไลบรารีเปิดอยู่ รายการต้องเป็นรายการเดียวกับในไฟล์ Manifest

ข้อผิดพลาดของบิลด์: เส้นทางไลบรารีที่ไม่รู้จัก

หากระบบบิลด์ไม่พบเส้นทางไปยังไฟล์ <uses-library> DEX jar (เส้นทางเวลาสร้างในโฮสต์หรือเส้นทางการติดตั้งในอุปกรณ์) โดยปกติแล้วระบบจะสร้างบิลด์ไม่สำเร็จ หากไม่พบเส้นทาง แสดงว่าไลบรารีได้รับการกําหนดค่าในลักษณะที่ไม่คาดคิด แก้ไขบิลด์ชั่วคราวโดยปิดใช้ dexpreopt สำหรับปัญหา

Android.bp (คุณสมบัติของโมดูล):

enforce_uses_libs: false,
dex_preopt: {
    enabled: false,
},

Android.mk (ตัวแปรของโมดูล):

LOCAL_ENFORCE_USES_LIBRARIES := false
LOCAL_DEX_PREOPT := false

รายงานข้อบกพร่องเพื่อตรวจสอบสถานการณ์ที่ไม่รองรับ

ข้อผิดพลาดของบิลด์: ไม่มีทรัพยากร Dependency ของไลบรารี

การพยายามเพิ่ม <uses-library> X จากไฟล์ Manifest ของโมดูล Y ไปยังไฟล์บิลด์ของ Y อาจส่งผลให้เกิดข้อผิดพลาดในการบิลด์เนื่องจากไม่มี X ซึ่งเป็นทรัพยากร Dependency

นี่คือตัวอย่างข้อความแสดงข้อผิดพลาดสำหรับโมดูล Android.bp:

"Y" depends on undefined module "X"

นี่คือตัวอย่างข้อความแสดงข้อผิดพลาดสำหรับโมดูล Android.mk

'.../JAVA_LIBRARIES/com.android.X_intermediates/dexpreopt.config', needed by '.../APPS/Y_intermediates/enforce_uses_libraries.status', missing and no known rule to make it

สาเหตุทั่วไปของข้อผิดพลาดดังกล่าวคือเมื่อมีการตั้งชื่อไลบรารีต่างจาก จะมีการตั้งชื่อโมดูลที่เกี่ยวข้องในระบบบิลด์ ตัวอย่างเช่น หากไฟล์ Manifest <uses-library> รายการคือ com.android.X แต่ชื่อของโมดูลไลบรารีคือ X จะทำให้เกิดข้อผิดพลาด ในการแก้ปัญหานี้ ให้บอกระบบบิลด์ว่า โมดูลชื่อ X จะระบุ <uses-library> ที่ชื่อว่า com.android.X

นี่คือตัวอย่างของไลบรารี Android.bp (พร็อพเพอร์ตี้ของโมดูล)

provides_uses_lib: “com.android.X”,

ตัวอย่างคลัง Android.mk (ตัวแปรโมดูล) มีดังนี้

LOCAL_PROVIDES_USES_LIBRARY := com.android.X

CLC ของเวลาบูตไม่ตรงกัน

เมื่อเปิดเครื่องครั้งแรก ให้ค้นหา Logcat เพื่อหาข้อความที่เกี่ยวข้องกับ CLC ที่ไม่ตรงกันดังที่แสดงด้านล่าง

$ adb wait-for-device && adb logcat \
  | grep -E 'ClassLoaderContext [a-z ]+ mismatch' -A1

เอาต์พุตอาจมีข้อความในรูปแบบที่แสดงที่นี่

[...] W system_server: ClassLoaderContext shared library size mismatch Expected=..., found=... (PCL[]... | PCL[]...)
[...] I PackageDexOptimizer: Running dexopt (dexoptNeeded=1) on: ...

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

บริบทของโปรแกรมโหลดคลาส

CLC เป็นโครงสร้างแบบต้นไม้ที่อธิบายลําดับชั้นของ Class Loader ระบบบิลด์ใช้ CLC ในความหมายที่แคบ (ครอบคลุมเฉพาะไลบรารี ไม่ใช่ APK หรือโปรแกรมโหลดคลาสที่กำหนดเอง) ซึ่งเป็นต้นไม้ของไลบรารีที่แสดงการปิดแบบทรานซิทีฟของ <uses-library> Dependency ทั้งหมดของไลบรารีหรือแอป องค์ประกอบระดับบนสุดของ CLC คือ <uses-library> Dependency โดยตรงที่ระบุไว้ในไฟล์ Manifest (Classpath) แต่ละโหนดของแผนผัง CLC คือ <uses-library> โหนดที่อาจมีโหนดย่อย <uses-library> โหนดของตัวเอง

เนื่องจาก <uses-library> Dependency เป็นกราฟแบบมีทิศทางที่ไม่เป็นวงจร และไม่จำเป็นต้องเป็นต้นไม้ CLC จึงมีซับต้นไม้หลายรายการสำหรับไลบรารีเดียวกันได้ ใน กล่าวอีกนัยหนึ่งคือ CLC คือกราฟการขึ้นต่อกันที่ "กางออก" ให้กับต้นไม้ การทำซ้ำ อยู่ในระดับที่เหมาะสมเท่านั้น ตัวโหลดคลาสที่อยู่เบื้องหลังจริงไม่ใช่ ซ้ำกัน (ที่รันไทม์จะมีอินสแตนซ์ตัวโหลดคลาสเดี่ยวสำหรับไลบรารีแต่ละรายการ)

CLC จะกำหนดลําดับการค้นหาของไลบรารีเมื่อแก้ไขคลาส Java ที่ใช้โดยไลบรารีหรือแอป ลําดับการค้นหามีความสําคัญเนื่องจากไลบรารีอาจมีคลาสที่ซ้ำกัน และระบบจะแก้ไขคลาสให้ตรงกับรายการแรกที่พบ

CLC ในอุปกรณ์ (รันไทม์)

PackageManager (ใน frameworks/base) สร้าง CLC เพื่อโหลดโมดูล Java ในอุปกรณ์ โดยจะเพิ่มไลบรารีที่แสดงในแท็ก <uses-library> ในส่วน เป็นองค์ประกอบ CLC ระดับบนสุด

สำหรับไลบรารีที่ใช้แต่ละรายการ PackageManager จะได้รับ <uses-library> ทั้งหมด ทรัพยากร Dependency (ระบุเป็นแท็กในไฟล์ Manifest ของไลบรารีนั้นๆ) และเพิ่ม CLC แบบฝังสำหรับทรัพยากร Dependency แต่ละรายการ กระบวนการนี้จะทําซ้ำแบบย้อนกลับจนกว่าโหนดใบทั้งหมดของต้นไม้ CLC ที่สร้างขึ้นจะเป็นไลบรารีที่ไม่มี<uses-library>ข้อกําหนด

PackageManager จะรับรู้เฉพาะคลังภาพที่แชร์เท่านั้น คำจำกัดความของ ที่แชร์ใน การใช้งานนี้แตกต่างจากความหมายปกติ (เช่น การแชร์กับแบบคงที่) ใน Android นั้น ไลบรารีที่แชร์ของ Java คือไลบรารีที่แสดงอยู่ในการกำหนดค่า XML ที่ติดตั้งในอุปกรณ์ (/system/etc/permissions/platform.xml) แต่ละรายการจะมีชื่อของไลบรารีที่แชร์ เส้นทางไปยังไฟล์ JAR ของ DEX และรายการ Dependency (ไลบรารีที่แชร์อื่นๆ ที่ใช้ไลบรารีนี้ในขณะรันไทม์ และระบุไว้ในแท็ก <uses-library> ในไฟล์ Manifest)

กล่าวคือ มีแหล่งข้อมูล 2 แหล่งที่อนุญาต PackageManager เพื่อสร้าง CLC ระหว่างรันไทม์: แท็ก <uses-library> ในไฟล์ Manifest และ ทรัพยากร Dependency ของไลบรารีที่แชร์ในการกำหนดค่า XML

CLC บนโฮสต์ (เวลาสร้าง)

CLC ไม่เพียงจำเป็นเมื่อโหลดไลบรารีหรือแอปเท่านั้น แต่ยังจำเป็นเมื่อคอมไพล์แอปด้วย การคอมไพล์อาจเกิดขึ้นในอุปกรณ์ (dexopt) หรือในระหว่าง สร้าง (dexpreopt) เนื่องจาก dexopt จะเกิดขึ้นในอุปกรณ์ จึงมี ข้อมูลเป็น PackageManager (ไฟล์ Manifest และทรัพยากร Dependency ของไลบรารีที่ใช้ร่วมกัน) อย่างไรก็ตาม Dexpreopt จะเกิดขึ้นในโฮสต์และแตกต่างจาก และต้องใช้ข้อมูลเดียวกันจากระบบบิลด์

ดังนั้น CLC เวลาบิลด์ที่ dexpreopt และ CLC ทำงานใช้โดย PackageManager เหมือนกัน แต่มีวิธีคำนวณ 2 วิธีที่แตกต่างกัน

CLC ของช่วงสร้างและช่วงรันไทม์ต้องตรงกัน มิฉะนั้นระบบจะปฏิเสธโค้ดที่คอมไพล์ AOT ซึ่งสร้างขึ้นโดย dexpreopt เพื่อตรวจสอบความเท่ากันของเวลาบิลด์และ CLC ที่รันไทม์ ซึ่งคอมไพเลอร์ dex2oat จะบันทึก CLC เวลาที่บิลด์ในไฟล์ *.odex (ในช่อง classpath ของส่วนหัวของไฟล์ OAT) หากต้องการค้นหา CLC ที่เก็บไว้ ให้ใช้คำสั่งนี้

oatdump --oat-file=<FILE> | grep '^classpath = '

CLC ที่เวลาบิลด์และรันไทม์ไม่ตรงกันใน Logcat ระหว่างการเปิดเครื่อง ค้นหา ด้วยคำสั่งนี้

logcat | grep -E 'ClassLoaderContext [a-z ]+ mismatch'

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

ไลบรารีที่ใช้ร่วมกันอาจเป็นแบบไม่บังคับหรือแบบบังคับก็ได้ จากมุมมองของ dexpreopt ไลบรารีที่จำเป็นต้องแสดงขึ้นขณะที่บิลด์ (หากไม่มี จะเป็นข้อผิดพลาดของบิลด์) ไลบรารีที่ไม่บังคับอาจมีหรือไม่มีก็ได้ ณ เวลาสร้าง หากมี ระบบจะเพิ่มลงใน CLC, ส่งไปยัง dex2oat และบันทึกไว้ในไฟล์ *.odex หากไม่มีไลบรารีที่ไม่บังคับ ระบบจะข้ามไลบรารีดังกล่าว และไม่ได้เพิ่มลงใน CLC หากสถานะเวลาสร้างและเวลารันไทม์ไม่ตรงกัน (มีไลบรารีที่ไม่บังคับในบางกรณี แต่ไม่มีในอีกกรณีหนึ่ง) แสดงว่า CLC ของเวลาสร้างและเวลารันไทม์ไม่ตรงกันและโค้ดที่คอมไพล์จะไม่ได้รับอนุมัติ

รายละเอียดระบบการสร้างขั้นสูง (เครื่องมือแก้ไขไฟล์ Manifest)

บางครั้งแท็ก <uses-library> ขาดหายไปจากไฟล์ Manifest ของแหล่งที่มาของไฟล์ ไลบรารีหรือแอป ซึ่งอาจเกิดขึ้นได้ เช่น หากทรัพยากร Dependency แบบทรานซิทีฟรายการหนึ่ง ของไลบรารีหรือแอปเริ่มใช้แท็ก <uses-library> อื่น และ ไลบรารีหรือไฟล์ Manifest ของแอปจะไม่อัปเดตให้รวมไฟล์ดังกล่าว

Soong สามารถคํานวณแท็ก <uses-library> ที่ขาดหายไปบางรายการสําหรับไลบรารีหรือแอปหนึ่งๆ โดยอัตโนมัติ เนื่องจากไลบรารี SDK อยู่ในชุดปิดของ Dependency แบบทรานซิทีฟของไลบรารีหรือแอปนั้น ชุดปิดจําเป็นเนื่องจากไลบรารี (หรือแอป) อาจขึ้นอยู่กับไลบรารีแบบคงที่ซึ่งขึ้นอยู่กับไลบรารี SDK และอาจขึ้นอยู่กับไลบรารีอื่นแบบทรานซิทีฟอีกครั้ง

แท็ก <uses-library> บางรายการไม่สามารถคํานวณด้วยวิธีนี้ได้ แต่หากเป็นไปได้ เราขอแนะนำให้ Soong เพิ่มรายการไฟล์ Manifest โดยอัตโนมัติ เนื่องจากจะลดข้อผิดพลาดและทําให้การดูแลรักษาง่ายขึ้น เช่น เมื่อแอปหลายแอปใช้ไลบรารีแบบคงที่ซึ่งเพิ่ม<uses-library> Dependency ใหม่ แอปทั้งหมดจะต้องอัปเดต ซึ่งทำให้ดูแลรักษาได้ยาก