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

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

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

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

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

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

ส่วนต่างๆ ของ Android ที่ได้รับผลกระทบ

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

การเปลี่ยนแปลงที่ส่งผลกับส่วนอื่นในระบบ

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

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

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

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

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

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

    PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true

    ใน Makefile ของผลิตภัณฑ์ การดำเนินการนี้จะแก้ไขข้อผิดพลาดในการสร้าง (ยกเว้นกรณีพิเศษ ที่ระบุไว้ในส่วนการแก้ไขการหยุดทำงาน) อย่างไรก็ตาม นี่เป็นวิธีแก้ปัญหาชั่วคราว และอาจทำให้ 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 ใน Makefile ของผลิตภัณฑ์ ระบบยังคงทำการตรวจสอบความสอดคล้องในเวลาบิลด์ แต่การตรวจสอบไม่สำเร็จไม่ได้หมายความว่าบิลด์จะล้มเหลว แต่หากการตรวจสอบไม่สำเร็จ ระบบบิลด์จะลดระดับตัวกรองคอมไพเลอร์ 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

นี่คือตัวอย่างข้อความแสดงข้อผิดพลาดสำหรับโมดูล 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 ไม่ตรงกันในเวลาบูต

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

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

บริบทของ Class Loader

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

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

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

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

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

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

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

กล่าวคือ มีแหล่งข้อมูล 2 แหล่งที่ช่วยให้ PackageManager สร้าง CLC ในรันไทม์ได้ ได้แก่ แท็ก <uses-library> ในไฟล์ Manifest และ การอ้างอิงไลบรารีที่ใช้ร่วมกันในการกำหนดค่า 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'

การไม่ตรงกันส่งผลเสียต่อประสิทธิภาพ เนื่องจากบังคับให้ไลบรารีหรือแอปต้อง dexopt หรือทํางานโดยไม่มีการเพิ่มประสิทธิภาพ (เช่น โค้ดของแอปอาจ ต้องแยกในหน่วยความจําจาก 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>การอ้างอิงใหม่ แอปทั้งหมดจะต้องได้รับการอัปเดต ซึ่งดูแลรักษายาก