Android 12 มีการเปลี่ยนแปลงระบบบิลด์การคอมไพล์ไฟล์ DEX (dexpreopt) สำหรับโมดูล Java ที่มีทรัพยากร Dependency <uses-library>
ในบางกรณี การเปลี่ยนแปลงระบบบิลด์เหล่านี้อาจทำให้บิลด์ใช้งานไม่ได้ ใช้หน้านี้เพื่อเตรียมพร้อมสำหรับการหยุดทำงาน และติดตามสูตรอาหารในหน้านี้เพื่อแก้ไขและบรรเทาปัญหา
Dexpreopt เป็นกระบวนการคอมไพล์ไลบรารี Java และแอปแบบล่วงหน้า Dexpreopt จะเกิดขึ้นบนโฮสต์เมื่อถึงเวลาสร้าง (ต่างจาก dexopt ซึ่งเกิดขึ้นในอุปกรณ์) โครงสร้างของทรัพยากร Dependency ของไลบรารีที่ใช้ร่วมกันซึ่งโมดูล Java (ไลบรารีหรือแอป) ใช้เรียกว่าบริบทตัวโหลดคลาส (CLC) CLC เวลาบิลด์และรันไทม์ต้องสอดคล้องกันเพื่อรับประกันความถูกต้องของ dexpreopt CLC ขณะสร้างคือสิ่งที่คอมไพเลอร์ dex2oat ใช้ ณ เวลา dexpreopt (บันทึกไว้ในไฟล์ ODEX) และ CLC ขณะรันไทม์คือบริบทที่โหลดโค้ดที่คอมไพล์ไว้ล่วงหน้าในอุปกรณ์
CLC ที่เวลาบิลด์และรันไทม์เหล่านี้ต้องสอดคล้องกันด้วยเหตุผลทั้งในแง่ความถูกต้องและประสิทธิภาพ คุณต้องจัดการกับชั้นเรียนที่ซ้ำกันเพื่อให้ถูกต้อง หากทรัพยากร Dependency ของไลบรารีที่ใช้ร่วมกันระหว่างรันไทม์ต่างจากทรัพยากร Dependency ที่ใช้สำหรับการคอมไพล์ คลาสบางคลาสอาจได้รับการแก้ไขแตกต่างกันไป ซึ่งทำให้เกิดข้อบกพร่องเล็กๆ น้อยๆ เกี่ยวกับรันไทม์ ประสิทธิภาพยังได้รับผลกระทบจากการตรวจสอบรันไทม์เพื่อหาคลาสที่ซ้ำกันด้วย
กรณีการใช้งานที่ได้รับผลกระทบ
การเปิดเครื่องครั้งแรกเป็นกรณีการใช้งานหลักที่ได้รับผลกระทบจากการเปลี่ยนแปลงเหล่านี้ โดยหาก ART ตรวจพบว่าเวลาบิลด์กับ CLC เวลาบิลด์กับรันไทม์ไม่ตรงกัน ก็จะปฏิเสธอาร์ติแฟกต์ dexpreopt แล้วเรียกใช้ dexopt แทน สำหรับการเปิดเครื่องครั้งต่อๆ ไปนั้นไม่เป็นไร เพราะคุณสามารถถอดรหัสแอปในเบื้องหลังและจัดเก็บไว้ในดิสก์ได้
พื้นที่ที่ได้รับผลกระทบของ Android
ซึ่งจะส่งผลต่อแอปและไลบรารี Java ทั้งหมดที่ต้องใช้ไลบรารี Java อื่นๆ ในรันไทม์ Android มีแอปหลายพันแอป และหลายร้อยแอปใช้ไลบรารีที่แชร์ พาร์ทเนอร์ก็ได้รับผลกระทบด้วย เนื่องจากมีพาร์ทเนอร์ไลบรารีและแอปของตนเอง
การเปลี่ยนแปลงช่วงพัก
ระบบบิลด์จำเป็นต้องรู้ทรัพยากร Dependency ของ <uses-library>
ก่อนที่จะสร้างกฎบิลด์ Dexpreopt แต่ไฟล์เข้าถึงไฟล์ Manifest โดยตรงและอ่านแท็ก <uses-library>
ในไฟล์ไม่ได้เนื่องจากระบบไม่ได้รับอนุญาตให้อ่านไฟล์ที่กำหนดเองเมื่อสร้างกฎการสร้าง (เพื่อเหตุผลด้านประสิทธิภาพ) ยิ่งไปกว่านั้น ไฟล์ Manifest
อาจอยู่ในแพ็กเกจที่อยู่ใน APK หรือแบบที่สร้างไว้ล่วงหน้า ดังนั้นข้อมูล <uses-library>
จึงต้องอยู่ในไฟล์บิลด์ (Android.bp
หรือ Android.mk
)
ก่อนหน้านี้ ART ใช้วิธีแก้ปัญหาที่ละเว้นการพึ่งพาไลบรารีที่ใช้ร่วมกัน (หรือที่เรียกว่า &-classpath
) ซึ่งไม่ปลอดภัยและทำให้เกิดข้อบกพร่องเล็กๆ น้อยๆ เราจึงนำวิธีแก้ปัญหานี้ออกใน Android 12
ดังนั้นโมดูล Java ที่ไม่ได้ให้ข้อมูล <uses-library>
ที่ถูกต้องในไฟล์บิลด์อาจทำให้เกิดการขัดข้องของบิลด์ (เกิดจาก CLC เวลาบิลด์ไม่ตรงกัน) หรือการถดถอยของเวลาเปิดเครื่องครั้งแรก (เกิดจากเวลา CLC ไม่ตรงกันตามด้วย dexopt)
เส้นทางการย้ายข้อมูล
ทำตามขั้นตอนต่อไปนี้เพื่อแก้ไขบิลด์ที่เสียหาย
ปิดใช้การตรวจสอบเวลาสร้างสำหรับผลิตภัณฑ์ที่เฉพาะเจาะจงทั่วโลกโดยการตั้งค่า
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
ในไฟล์ยี่ห้อผลิตภัณฑ์ ซึ่งจะแก้ไขข้อผิดพลาดของบิลด์ (ยกเว้นบางกรณีพิเศษที่ระบุไว้ในส่วนการแก้ไขข้อขัดข้อง) อย่างไรก็ตาม นี่เป็นวิธีแก้ปัญหาชั่วคราว และอาจทำให้ CLC เวลาเปิดเครื่องไม่ตรงกัน ตามด้วย dexopt
แก้ไขโมดูลที่ไม่ผ่านการตรวจสอบก่อนที่คุณปิดใช้การตรวจสอบเวลาสร้างทั่วโลกโดยเพิ่มข้อมูล
<uses-library>
ที่จำเป็นลงในไฟล์บิลด์ (ดูรายละเอียดที่การแก้ไขข้อขัดข้อง) สำหรับโมดูลส่วนใหญ่ คุณต้องเพิ่มบรรทัด 2-3 บรรทัดในAndroid.bp
หรือAndroid.mk
ปิดใช้การตรวจสอบเวลาบิลด์และ dexpreopt สำหรับกรณีที่เป็นปัญหาสำหรับแต่ละโมดูล ปิดใช้ dexpreopt เพื่อไม่ให้เสียเวลาสร้างและพื้นที่เก็บข้อมูลกับอาร์ติแฟกต์ที่ถูกปฏิเสธเมื่อบูต
เปิดใช้การตรวจสอบเวลาสร้างอีกครั้งโดยยกเลิกการตั้งค่า
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES
ที่ตั้งไว้ในขั้นตอนที่ 1 การสร้างไม่ควรล้มเหลวหลังจากการเปลี่ยนแปลงนี้ (เนื่องจากขั้นตอนที่ 2 และ 3)แก้ไขโมดูลที่คุณปิดใช้ในขั้นตอนที่ 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
ในไฟล์ Make ของผลิตภัณฑ์ การตรวจสอบความสอดคล้องของเวลาบิลด์ยังดำเนินการอยู่ แต่การตรวจสอบที่ไม่สำเร็จไม่ได้หมายความว่าการสร้างล้มเหลว แต่การตรวจสอบที่ไม่สําเร็จจะทำให้ระบบบิลด์ดาวน์เกรดตัวกรองคอมไพเลอร์ 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
:
มองหาไลบรารีที่ขาดหายไปในพร็อพเพอร์ตี้
libs
ของโมดูล หากมี ปกติแล้ว Soong จะเพิ่มคลังดังกล่าวโดยอัตโนมัติ ยกเว้นในกรณีพิเศษต่อไปนี้- ไลบรารีไม่ใช่ไลบรารี SDK (กำหนดให้เป็น
java_library
ไม่ใช่java_sdk_library
) - ไลบรารีมีชื่อไลบรารี (ในไฟล์ Manifest) แตกต่างจากชื่อโมดูล (ในระบบบิลด์)
หากต้องการแก้ไขปัญหานี้ชั่วคราว ให้เพิ่ม
provides_uses_lib: "<library-name>"
ในคําจํากัดความของไลบรารีAndroid.bp
สำหรับโซลูชันระยะยาว ให้แก้ไขปัญหาที่แท้จริง: แปลงไลบรารีเป็นไลบรารี SDK หรือเปลี่ยนชื่อโมดูล- ไลบรารีไม่ใช่ไลบรารี SDK (กำหนดให้เป็น
หากขั้นตอนก่อนหน้าไม่ได้ช่วยแก้ปัญหา ให้เพิ่ม
uses_libs: ["<library-module-name>"]
สำหรับไลบรารีที่ต้องระบุ หรือoptional_uses_libs: ["<library-module-name>"]
สำหรับไลบรารีที่ไม่บังคับลงในคําจํากัดความAndroid.bp
ของโมดูล ซึ่งพร็อพเพอร์ตี้เหล่านี้จะยอมรับ รายการชื่อโมดูล ลำดับแบบสัมพัทธ์ของไลบรารีในรายการต้องเหมือนกับลำดับในไฟล์ Manifest
สำหรับโมดูล Android.mk
:
ตรวจสอบว่าไลบรารีมีชื่อไลบรารี (ในไฟล์ Manifest) แตกต่างจากชื่อโมดูล (ในระบบบิลด์) หรือไม่ หากมี ให้แก้ไขปัญหานี้ชั่วคราวโดยเพิ่ม
LOCAL_PROVIDES_USES_LIBRARY := <library-name>
ในไฟล์Android.mk
ของไลบรารี หรือเพิ่มprovides_uses_lib: "<library-name>"
ในไฟล์Android.bp
ของไลบรารี (ทั้ง 2 กรณีเป็นไปได้เนื่องจากโมดูลAndroid.mk
อาจขึ้นอยู่กับไลบรารีAndroid.bp
) สำหรับการแก้ปัญหาในระยะยาว ให้แก้ไขปัญหาพื้นฐานซึ่งก็คือเปลี่ยนชื่อโมดูลไลบรารีเพิ่ม
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 อาจทำให้เกิดข้อผิดพลาดของบิลด์เนื่องจากไม่มีทรัพยากร Dependency 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>
ของไฟล์ Manifest คือ 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 อื่น ไม่ใช่ไลบรารี) ระบบบิลด์ไม่สามารถจัดการกับทุกกรณีได้ เนื่องจากในขั้นตอนการบิลด์ เราไม่อาจทราบได้อย่างแน่ชัดว่าแอปจะโหลดอะไรในรันไทม์
บริบทของตัวโหลดชั้นเรียน
CLC เป็นโครงสร้างแบบต้นไม้ที่อธิบายลําดับชั้นของ Class Loader ระบบบิลด์ใช้ CLC ในความหมายที่แคบ (ครอบคลุมเฉพาะไลบรารี ไม่ใช่ APK หรือโปรแกรมโหลดคลาสที่กำหนดเอง) ซึ่งเป็นต้นไม้ของไลบรารีที่แสดงการปิดแบบทรานซิทีฟของ <uses-library>
ทั้งหมดที่ไลบรารีหรือแอปต้องใช้ องค์ประกอบระดับบนสุดของ CLC คือ <uses-library>
โดยตรงที่ระบุไว้ในไฟล์ Manifest (คลาสพาธ) แต่ละโหนดของแผนผัง CLC คือโหนด <uses-library>
ที่อาจมีโหนดย่อย <uses-library>
ของตัวเอง
เนื่องจาก <uses-library>
Dependency เป็นกราฟแบบมีทิศทางที่ไม่เป็นวงจร และไม่จำเป็นต้องเป็นต้นไม้ CLC จึงมีซับต้นไม้หลายรายการสำหรับไลบรารีเดียวกันได้ กล่าวคือ CLC คือกราฟทรัพยากร Dependency "ที่กางออก" ของแผนภูมิต้นไม้ การทำซ้ำจะอยู่ในระดับเชิงตรรกะเท่านั้น ตัวโหลดคลาสที่สำคัญจริงจะไม่ซ้ำซ้อน (ที่รันไทม์จะมีอินสแตนซ์ตัวโหลดคลาสเดี่ยวสำหรับไลบรารีแต่ละรายการ)
CLC จะกำหนดลำดับการค้นหาของไลบรารีเมื่อจับคู่คลาสของ Java ที่ไลบรารีหรือแอปใช้ ลำดับการค้นหามีความสำคัญเนื่องจากไลบรารีอาจมีคลาสที่ซ้ำกันได้ และคลาสจะได้รับการแก้ไขให้ตรงกันรายการแรก
CLC ในอุปกรณ์ (รันไทม์)
PackageManager
(ใน frameworks/base
) สร้าง CLC เพื่อโหลดข้อบังคับ Java ในอุปกรณ์ โดยจะเพิ่มไลบรารีที่แสดงอยู่ในแท็ก <uses-library>
ในไฟล์ Manifest ของข้อบังคับเป็นองค์ประกอบ CLC ระดับบนสุด
สำหรับไลบรารีที่ใช้แต่ละรายการ PackageManager
จะได้รับการอ้างอิง <uses-library>
ทั้งหมด (ระบุเป็นแท็กในไฟล์ 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 โดยอัตโนมัติ เนื่องจากจะลดข้อผิดพลาดและทําให้การดูแลรักษาง่ายขึ้น เช่น เมื่อแอปจำนวนมากใช้ไลบรารีแบบคงที่ที่เพิ่มทรัพยากร Dependency ของ <uses-library>
ใหม่ แอปทั้งหมดจะต้องได้รับการอัปเดต จึงดูแลยาก