Dexpreopt और <uses-library> की जांच

Android 12 में, DEX फ़ाइलों (dexpreopt) के एओटी कंपाइलेशन के लिए, बिल्ड सिस्टम में बदलाव किए गए हैं. ये बदलाव, उन Java मॉड्यूल के लिए किए गए हैं जिनमें <uses-library> डिपेंडेंसी मौजूद हैं. कुछ मामलों में बिल्ड सिस्टम में किए गए ये बदलाव टूट सकते हैं बिल्ड. इस पेज का इस्तेमाल करके गड़बड़ियों की तैयारी करें और इसकी रेसिपी फ़ॉलो करें मदद ली जा सकती है.

Dexpreopt, Java लाइब्रेरी और ऐप्लिकेशन को पहले से कंपाइल करने की प्रोसेस है. Dexpreopt, बिल्ड के समय होस्ट पर होता है (dexopt के उलट, जो उपयोगकर्ता, डिवाइस पर ही होते हैं). Java की ओर से इस्तेमाल की जाने वाली शेयर लाइब्रेरी डिपेंडेंसी का स्ट्रक्चर मॉड्यूल (लाइब्रेरी या ऐप्लिकेशन) को उसके क्लास लोडर कॉन्टेक्स्ट (सीएलसी) के तौर पर जाना जाता है. dexpreopt के सही होने की गारंटी देने के लिए, बिल्ड टाइम और रन टाइम सीएलसी एक जैसे होने चाहिए. बिल्ड टाइम सीएलसी वह है जिसका इस्तेमाल dex2oat कंपाइलर, dexpreopt के समय करता है (इसे ODEX फ़ाइलों में रिकॉर्ड किया जाता है). वहीं, रन-टाइम सीएलसी वह कॉन्टेक्स्ट है जिसमें डिवाइस पर पहले से कंपाइल किया गया कोड लोड किया जाता है.

बिल्ड-टाइम और रन-टाइम सीएलसी, दोनों के सही होने की वजहों से मेल खाने चाहिए साथ ही, परफ़ॉर्मेंस को बेहतर बनाने के लिए भी किया जा सकता है. सही जानकारी देने के लिए, डुप्लीकेट क्लास को मैनेज करना ज़रूरी है. अगर रनटाइम के दौरान शेयर की गई लाइब्रेरी की डिपेंडेंसी, कॉम्पाइल करने के लिए इस्तेमाल की गई डिपेंडेंसी से अलग हैं, तो हो सकता है कि कुछ क्लास अलग तरीके से रिज़ॉल्व हों. इससे रनटाइम के दौरान छोटे-मोटे गड़बड़ियां हो सकती हैं. डुप्लीकेट कॉपी के लिए रनटाइम की जांच से भी परफ़ॉर्मेंस पर असर पड़ता है क्लास.

इस्तेमाल के वे उदाहरण जिन पर असर पड़ा है

इन बदलावों का असर, पहली बार बूट करने के दौरान ही पड़ता है: अगर ART बिल्ड-टाइम और रन-टाइम सीएलसी के बीच अंतर का पता लगाता है, तो यह dexpreopt को अस्वीकार करता है और इसके बजाय डिकोड करता है. बाद के बूट के लिए यह ठीक है, क्योंकि ऐप्लिकेशन को बैकग्राउंड से हटाकर डिस्क में सेव किया जा सकता है.

Android के प्रभावित क्षेत्र

इससे उन सभी Java ऐप्लिकेशन और लाइब्रेरी पर असर पड़ता है जिनमें रनटाइम के दौरान, दूसरी Java लाइब्रेरी पर निर्भरता होती है. Android पर हज़ारों ऐप्लिकेशन मौजूद हैं और उनमें से सैकड़ों शेयर की गई लाइब्रेरी पर टैप करें. पार्टनर पर इस बदलाव का असर, जैसे कि उनके अपने पहले से होगा लाइब्रेरी और ऐप्लिकेशन शामिल हैं.

बदलावों को लागू करें

dexpreopt के लिए बने बिल्ड नियम जनरेट करने से पहले, बिल्ड सिस्टम को <uses-library> की डिपेंडेंसी के बारे में पता होना चाहिए. हालांकि, यह सीधे तौर पर मेनिफ़ेस्ट को ऐक्सेस नहीं कर सकता और उसमें मौजूद <uses-library> टैग को नहीं पढ़ सकता. इसकी वजह यह है कि परफ़ॉर्मेंस से जुड़ी वजहों से, बिल्ड सिस्टम को बिल्ड नियम जनरेट करते समय, मनमुताबिक फ़ाइलें पढ़ने की अनुमति नहीं होती. इसके अलावा, मेनिफ़ेस्ट में इन्हें किसी APK या पहले से बने हुए ऐप्लिकेशन में पैक किया जा सकता है. इसलिए, <uses-library> जानकारी, बिल्ड फ़ाइलों (Android.bp या Android.mk) में मौजूद होनी चाहिए.

पहले ART ने शेयर की गई लाइब्रेरी डिपेंडेंसी को अनदेखा करने के लिए एक समाधान का इस्तेमाल किया था ( &-classpath). यह असुरक्षित था और इसकी वजह से छोटी-मोटी गड़बड़ियां हुईं. इसलिए, Android 12 में हटा दिया गया था.

इस वजह से, ऐसे Java मॉड्यूल जो सही <uses-library> नहीं देते हैं उनकी बिल्ड फ़ाइलों में मौजूद जानकारी की वजह से बिल्ड के दौरान आने वाली समस्याएं हो सकती हैं. इन गड़बड़ियों की वजह से बिल्ड-टाइम सीएलसी मैच नहीं होता है या फ़र्स्ट-बूट टाइम रिग्रेशन (बूट-टाइम की वजह से होता है) सीएलसी मैच नहीं हो रहा है, इसके बाद dexopt).

माइग्रेशन पाथ

गड़बड़ी वाले बिल्ड को ठीक करने के लिए, यह तरीका अपनाएं:

  1. किसी प्रॉडक्ट के लिए, बिल्ड-टाइम की जांच की सुविधा को दुनिया भर में बंद करें. इसके लिए,

    PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true

    में मौजूद है. इससे, गड़बड़ियों को ठीक करना सेक्शन में बताए गए खास मामलों को छोड़कर, बिल्ड से जुड़ी गड़बड़ियां ठीक हो जाती हैं. हालांकि, यह अस्थायी समाधान है. इसकी वजह से हो सकता है कि बूट-टाइम सीएलसी मेल न खाए इसके बाद, dexopt का इस्तेमाल किया जाता है.

  2. बिल्ड-टाइम की जांच की सुविधा को सभी देशों में बंद करने से पहले, फ़ेल हुए मॉड्यूल को ठीक करें इसके लिए, <uses-library> में ज़रूरी जानकारी जोड़ें को अपनी बिल्ड फ़ाइलों में जोड़ा जा सकता है (ज़्यादा जानकारी के लिए गड़बड़ियां ठीक करना देखें). ज़्यादातर मॉड्यूल के लिए, Android.bp या Android.mk.

  3. समस्या वाले मामलों में बिल्ड-टाइम की जांच करने और उनके जवाब देने की सुविधा बंद करें, हर मॉड्यूल के हिसाब से. dexpreopt को बंद करें, ताकि बूट होने पर अस्वीकार होने वाले आर्टफ़ैक्ट पर, बिल्ड के समय और स्टोरेज को बर्बाद न किया जाए.

  4. इस सुविधा को अनसेट करके, बिल्ड-टाइम की जांच को दुनिया भर में फिर से चालू करें PRODUCT_BROKEN_VERIFY_USES_LIBRARIES जिसे पहले चरण में सेट किया गया था; बिल्ड इस परिवर्तन के बाद विफल नहीं होना चाहिए (चरण 2 और 3 की वजह से).

  5. तीसरे चरण में बंद किए गए मॉड्यूल को एक-एक करके ठीक करें. इसके बाद, उन्हें फिर से चालू करें dexpreopt और <uses-library> चेक. अगर ज़रूरी हो, तो गड़बड़ियों की शिकायत करें.

बिल्ड-टाइम <uses-library> जांच की सुविधा, Android 12 में लागू की गई है.

गड़बड़ियां ठीक करना

नीचे दिए गए सेक्शन में, अलग-अलग तरह की गड़बड़ियों को ठीक करने का तरीका बताया गया है.

बिल्ड में गड़बड़ी: सीएलसी मैच नहीं हो रहा

बिल्ड सिस्टम, बिल्ड के समय Android.bp या Android.mk फ़ाइलों और मेनिफ़ेस्ट में मौजूद जानकारी की जांच करता है. बिल्ड सिस्टम पढ़ नहीं सकता मेनिफ़ेस्ट फ़ाइल को पढ़ सकता है, लेकिन वह मेनिफ़ेस्ट को पढ़ने के लिए बिल्ड नियम बना सकता है (एक्सट्रैक्ट करने के लिए इसे APK से भी हटा सकते हैं) और मेनिफ़ेस्ट में <uses-library> टैग की तुलना करें बिल्ड फ़ाइलों में मौजूद <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. बिल्ड-टाइम में काम की जानकारी की जांच अब भी की जा रही है. हालांकि, जांच में गड़बड़ी का मतलब यह नहीं है कि बिल्ड में गड़बड़ी. इसके बजाय, अगर जांच में कोई गड़बड़ी होती है, तो बिल्ड सिस्टम dexpreopt में, verify के लिए dex2oat कंपाइलर फ़िल्टर, जो 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. अगर पिछले चरण से समस्या हल नहीं हुई, तो मॉड्यूल की Android.bp परिभाषा में, ज़रूरी लाइब्रेरी के लिए uses_libs: ["<library-module-name>"] या वैकल्पिक लाइब्रेरी के लिए optional_uses_libs: ["<library-module-name>"] जोड़ें. ये प्रॉपर्टी सूची में मौजूद का इस्तेमाल किया जा सकता है. सूची में लाइब्रेरी का क्रम, मेनिफ़ेस्ट में दिए गए क्रम जैसा होना चाहिए.

Android.mk मॉड्यूल के लिए:

  1. देखें कि लाइब्रेरी का नाम (मैनफ़ेस्ट में) और मॉड्यूल का नाम (बिल्ड सिस्टम में) अलग-अलग है या नहीं. अगर ऐसा होता है, तो कुछ समय के लिए इसकी Android.mk फ़ाइल में LOCAL_PROVIDES_USES_LIBRARY := <library-name> लाइब्रेरी या Android.bp में provides_uses_lib: "<library-name>" जोड़ें लाइब्रेरी की फ़ाइल (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

काम न करने वाली स्थितियों की जांच करने के लिए, गड़बड़ी की शिकायत करें.

बिल्ड करने में हुई गड़बड़ी: लाइब्रेरी की डिपेंडेंसी मौजूद नहीं है

बिल्ड में मॉड्यूल Y के मेनिफ़ेस्ट से <uses-library> X को जोड़ने की कोशिश की गई 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 नाम का मॉड्यूल, com.android.X नाम का <uses-library> उपलब्ध कराता है.

यह Android.bp लाइब्रेरी (मॉड्यूल प्रॉपर्टी) का उदाहरण है:

provides_uses_lib: “com.android.X”,

यह Android.mk लाइब्रेरी (मॉड्यूल वैरिएबल) का उदाहरण है:

LOCAL_PROVIDES_USES_LIBRARY := com.android.X

बूट-टाइम सीएलसी मेल नहीं खाता

पहली बार बूट करने पर, सीएलसी से मेल न खाने वाले मैसेज के लिए 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: ...

अगर आपको सीएलसी मेल न खाने की चेतावनी मिलती है, तो गड़बड़ी वाले मॉड्यूल के लिए dexopt निर्देश देखें. इसे ठीक करने के लिए, पक्का करें कि मॉड्यूल के लिए बिल्ड टाइम की जांच पूरी हो गई हो. अगर ऐसा नहीं होता है, तो हो सकता है कि आपका ऐप्लिकेशन एक ऐसा खास ऐप्लिकेशन हो जो बिल्ड सिस्टम के साथ काम न करता हो. जैसे, कोई ऐसा ऐप्लिकेशन जो लाइब्रेरी के बजाय कोई दूसरा APK लोड करता हो. बिल्ड सिस्टम, सभी मामलों को मैनेज नहीं करता. ऐसा इसलिए, क्योंकि बिल्ड के समय यह पता करना असंभव होता है कि रनटाइम के दौरान ऐप्लिकेशन क्या लोड करता है.

क्लास लोडर का कॉन्टेक्स्ट

सीएलसी, ट्री जैसा स्ट्रक्चर होता है. इसमें क्लास-लोडर हैरारकी के बारे में बताया जाता है. कॉन्टेंट बनाने बिल्ड सिस्टम में सीएलसी का इस्तेमाल कम शब्दों में किया जाता है (यह सिर्फ़ लाइब्रेरी को कवर करता है, APKs नहीं या कस्टम-क्लास लोडर): यह लाइब्रेरी का एक ट्री है, जो ट्रांज़िटिव तरीके से दिखाता है लाइब्रेरी या ऐप्लिकेशन की सभी <uses-library> डिपेंडेंसी को बंद करना. टॉप लेवल सीएलसी के एलिमेंट, सीधे तौर पर बताई गई <uses-library> डिपेंडेंसी हैं को मेनिफ़ेस्ट (क्लासपाथ) में सेव करें. सीएलसी ट्री का हर नोड एक <uses-library> नोड होता है, जिसमें अपने <uses-library> सब-नोड हो सकते हैं.

ऐसा इसलिए हुआ, क्योंकि <uses-library> डिपेंडेंसी, डायरेक्ट असाइकलिक ग्राफ़ होते हैं, न कि अगर सीएलसी एक ट्री है, तो उसमें एक ही लाइब्रेरी के लिए कई सबट्री हो सकती हैं. तय सीमा में दूसरे शब्दों में, सीएलसी डिपेंडेंसी ग्राफ़ "अनफ़ोल्डेड" होता है एक पेड़ तक सीमित. डुप्लीकेटेशन सिर्फ़ लॉजिकल लेवल पर होता है. असल क्लास लोडर का डुप्लीकेट नहीं होता. रनटाइम के दौरान, हर लाइब्रेरी के लिए एक क्लास लोडर इंस्टेंस होता है.

लाइब्रेरी या ऐप्लिकेशन में इस्तेमाल की गई Java क्लास को हल करते समय, सीएलसी लाइब्रेरी के लुकअप ऑर्डर तय करता है. लुकअप ऑर्डर ज़रूरी है, क्योंकि लाइब्रेरी में डुप्लीकेट क्लास हो सकती हैं और क्लास को पहले मैच के हिसाब से हल किया जाता है.

डिवाइस पर (रन-टाइम) सीएलसी

PackageManager (frameworks/base में), डिवाइस पर Java मॉड्यूल लोड करने के लिए सीएलसी बनाता है. यह मॉड्यूल के <uses-library> टैग में मौजूद लाइब्रेरी जोड़ देता है मेनिफ़ेस्ट को टॉप-लेवल सीएलसी एलिमेंट के तौर पर दिखाना चाहिए.

इस्तेमाल की गई हर लाइब्रेरी के लिए, PackageManager को उसकी सभी <uses-library> डिपेंडेंसी (उस लाइब्रेरी के मेनिफ़ेस्ट में टैग के तौर पर बताई गई) मिलती हैं. साथ ही, हर डिपेंडेंसी के लिए नेस्ट किया गया सीएलसी जोड़ता है. यह प्रोसेस तब तक बार-बार चलती रहती है, जब तक कि बनाए गए सीएलसी ट्री के सभी लीफ नोड, <uses-library> डिपेंडेंसी के बिना लाइब्रेरी न हों.

PackageManager को सिर्फ़ शेयर की गई लाइब्रेरी की जानकारी है. इस इस्तेमाल में, शेयर किए गए का मतलब, सामान्य तौर पर शेयर किए जाने के मतलब से अलग होता है. जैसे, शेयर किए गए बनाम स्टैटिक. Android में, डिवाइस पर इंस्टॉल की गई (/system/etc/permissions/platform.xml) एक्सएमएल कॉन्फ़िगरेशन में मौजूद, Java की शेयर की गई लाइब्रेरी को शेयर की गई लाइब्रेरी कहा जाता है. हर एंट्री में, शेयर की गई लाइब्रेरी का नाम, उसकी DEX jar फ़ाइल का पाथ, और डिपेंडेंसी की सूची होती है. डिपेंडेंसी, ऐसी अन्य शेयर की गई लाइब्रेरी होती हैं जिनका इस्तेमाल, रनटाइम के दौरान किया जाता है. साथ ही, इनके बारे में मेनिफ़ेस्ट में <uses-library> टैग में बताया जाता है.

दूसरे शब्दों में, जानकारी के दो सोर्स हैं जिनकी मदद से PackageManager, रनटाइम के दौरान सीएलसी बना सकता है: मेनिफ़ेस्ट में <uses-library> टैग और एक्सएमएल कॉन्फ़िगरेशन में शेयर की गई लाइब्रेरी की डिपेंडेंसी.

होस्ट पर (बिल्ड के समय) सीएलसी

लाइब्रेरी या ऐप्लिकेशन को लोड करने के साथ-साथ, उसे संकलित करने के लिए भी सीएलसी की ज़रूरत होती है. कंपाइलेशन, डिवाइस पर (dexopt) या बाइल्ड के दौरान (dexpreopt) हो सकता है. डिक्सोप्ट डिवाइस पर होता है, इसलिए यह प्रक्रिया भी उतनी ही ज़रूरी है PackageManager (मेनिफ़ेस्ट और शेयर की गई लाइब्रेरी डिपेंडेंसी) के तौर पर जानकारी. हालांकि, Dexpreopt, होस्ट पर और एक अलग इकोसिस्टम में होता है. साथ ही, इसे बिल्ड सिस्टम से वही जानकारी मिलती है.

इसलिए, dexpreopt के इस्तेमाल किए गए बिल्ड-टाइम सीएलसी और PackageManager के इस्तेमाल किए गए रन-टाइम सीएलसी, एक ही चीज़ हैं. हालांकि, इनका हिसाब दो अलग-अलग तरीकों से लगाया जाता है.

बिल्ड टाइम और रन टाइम सीएलसी एक जैसे होने चाहिए. ऐसा न होने पर, dexpreopt की मदद से बनाया गया AOT-कंपाइल किया गया कोड अस्वीकार कर दिया जाता है. बिल्ड-टाइम के बीच समानता की जांच करने के लिए और रन-टाइम सीएलसी, dex2oat कंपाइलर *.odex फ़ाइलों में बिल्ड-टाइम सीएलसी रिकॉर्ड करता है (OAT फ़ाइल हेडर के classpath फ़ील्ड में). सेव की गई सीएलसी ढूंढने के लिए, इस कमांड का इस्तेमाल करें:

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

बूट के दौरान, logcat में बिल्ड टाइम और रन टाइम के सीएलसी के मेल न खाने की जानकारी दी जाती है. इस कमांड का इस्तेमाल करके इसे खोजें:

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

मैच न होने की वजह से परफ़ॉर्मेंस खराब होती है, क्योंकि इससे लाइब्रेरी या ऐप्लिकेशन हटाया जा सकता है या ऑप्टिमाइज़ेशन के बिना चलाया जा सकता है (उदाहरण के लिए, ऐप्लिकेशन का कोड APK से मेमोरी में एक्सट्रैक्ट करने की ज़रूरत होती है, जो एक बहुत महंगा ऑपरेशन है).

शेयर की गई लाइब्रेरी ज़रूरी हो सकती है या विकल्प के तौर पर उपलब्ध हो सकती है. इन्होंने भेजा: विकल्प के रूप में, बिल्ड के समय एक ज़रूरी लाइब्रेरी मौजूद होनी चाहिए (इसकी होने की वजह से बिल्ड में गड़बड़ी हुई है). कोई वैकल्पिक लाइब्रेरी मौजूद या मौजूद नहीं हो सकती बिल्ड टाइम पर मौजूद होता है: अगर यह मौजूद है, तो उसे सीएलसी में जोड़ दिया जाता है, dex2oat पर भेजा जाता है, और *.odex फ़ाइल में रिकॉर्ड किया गया है. अगर कोई लाइब्रेरी उपलब्ध नहीं है, तो उसे छोड़ दिया जाता है और सीएलसी में नहीं जोड़ा जाता. अगर बिल्ड टाइम और रन टाइम स्टेटस के बीच कोई मैच नहीं होता है (एक मामले में वैकल्पिक लाइब्रेरी मौजूद है, लेकिन दूसरे में नहीं), तो बिल्ड टाइम और रन टाइम सीएलसी मैच नहीं होते और कंपाइल किया गया कोड अस्वीकार कर दिया जाता है.

बिल्ड सिस्टम की बेहतर जानकारी (मेनिफ़ेस्ट फ़िक्सर)

कभी-कभी किसी टैग के सोर्स मेनिफ़ेस्ट में <uses-library> टैग मौजूद नहीं होते हैं लाइब्रेरी या ऐप्लिकेशन से पैसे चुकाते हैं. उदाहरण के लिए, ऐसा तब हो सकता है, जब ट्रांज़िटिव डिपेंडेंसी में से कोई एक लाइब्रेरी या ऐप्लिकेशन किसी दूसरे <uses-library> टैग का इस्तेमाल करना शुरू कर देता है और को शामिल करने के लिए, लाइब्रेरी या ऐप्लिकेशन के मेनिफ़ेस्ट को अपडेट नहीं किया गया है.

Soong, किसी लाइब्रेरी या ऐप्लिकेशन के लिए, छूटे हुए कुछ <uses-library> टैग का हिसाब अपने-आप लगा सकता है. ऐसा इसलिए, क्योंकि लाइब्रेरी या ऐप्लिकेशन की ट्रांज़िटिव डिपेंडेंसी क्लोज़र में SDK टूल की लाइब्रेरी शामिल होती हैं. क्लोज़र की ज़रूरत इसलिए होती है, क्योंकि लाइब्रेरी (या ऐप्लिकेशन) किसी ऐसी स्टैटिक लाइब्रेरी पर निर्भर हो सकती है जो किसी SDK टूल की लाइब्रेरी पर निर्भर करती है. साथ ही, हो सकता है कि वह फिर से किसी दूसरी लाइब्रेरी के ज़रिए ट्रांज़िटिव तौर पर निर्भर हो.

सभी <uses-library> टैग को इस तरह से कैलकुलेट नहीं किया जा सकता. हालांकि, जब भी हो सके, Soong को मेनिफ़ेस्ट एंट्री अपने-आप जोड़ने दें. इससे गड़बड़ी की संभावना कम होती है और रखरखाव आसान हो जाता है. उदाहरण के लिए, जब कई ऐप्लिकेशन स्टैटिक लाइब्रेरी जो एक नई <uses-library> डिपेंडेंसी जोड़ती है, सभी ऐप्लिकेशन जिसे बनाए रखना मुश्किल है.