Dexpreopt และ <uses-library> เช็ค

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

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

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

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

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

พื้นที่ที่ได้รับผลกระทบจาก Android

สิ่งนี้ส่งผลต่อแอพและไลบรารี Java ทั้งหมดที่มีการพึ่งพารันไทม์บนไลบรารี 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> ที่จำเป็นลงในไฟล์บิลด์ (ดู การแก้ไขการแตกหัก เพื่อดูรายละเอียด) สำหรับโมดูลส่วนใหญ่ จำเป็นต้องเพิ่มสองสามบรรทัดใน 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> ในรายการ การตรวจสอบข้อความแสดงข้อผิดพลาดจะแสดงว่าไลบรารีใดที่ทำให้เกิดปัญหา (เช่นเดียวกับการตรวจสอบ AndroidManifest.xml หรือรายการภายใน APK ที่สามารถตรวจสอบได้ด้วย ` aapt dump badging $APK | grep uses-library `)

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

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

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

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

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

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

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

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

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

หากระบบบิลด์ไม่พบเส้นทางไปยัง <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

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

ข้อผิดพลาดของบิลด์: ขาดการพึ่งพาไลบรารี

ความพยายามในการเพิ่ม <uses-library> X จากรายการของโมดูล 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

สาเหตุทั่วไปของข้อผิดพลาดดังกล่าวคือเมื่อมีการตั้งชื่อไลบรารีแตกต่างจากการตั้งชื่อโมดูลที่เกี่ยวข้องในระบบบิลด์ ตัวอย่างเช่น หากรายการ <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 เป็นโครงสร้างแบบต้นไม้ที่อธิบายลำดับชั้นของคลาสโหลดเดอร์ ระบบบิลด์ใช้ CLC ในแง่แคบ (ครอบคลุมเฉพาะไลบรารี ไม่ใช่ APK หรือตัวโหลดคลาสที่กำหนดเอง): เป็นแผนผังของไลบรารีที่แสดงถึงการปิดแบบสกรรมกริยาของการขึ้นต่อกันของ <uses-library> ทั้งหมดของไลบรารีหรือแอป องค์ประกอบระดับบนสุดของ CLC คือการพึ่งพา <uses-library> โดยตรงที่ระบุในรายการ (classpath) แต่ละโหนดของแผนผัง CLC คือโหนด <uses-library> ที่อาจมีโหนดย่อย <uses-library> ของตัวเอง

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

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

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

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

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

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

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

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

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

ดังนั้น CLC ในเวลาบิลด์ที่ใช้โดย dexpreopt และ CLC รันไทม์ที่ใช้โดย PackageManager จึงเป็นสิ่งเดียวกัน แต่คำนวณด้วยสองวิธีที่แตกต่างกัน

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

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

CLC เวลาบิลด์และเวลารันไทม์ไม่ตรงกันถูกรายงานใน logcat ระหว่างการบู๊ต ค้นหาด้วยคำสั่งนี้:

logcat | grep -E 'ClassLoaderContext [az ]+ mismatch'

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

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

รายละเอียดระบบบิลด์ขั้นสูง (ตัวแก้ไขรายการ)

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

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

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