Android 12 में, Java मॉड्यूल के लिए DEX फ़ाइलों (dexpreopt) के AOT कंपाइलेशन के लिए, बिल्ड सिस्टम में बदलाव किए गए हैं
. इन मॉड्यूल में <uses-library>
डिपेंडेंसी होती हैं. कुछ मामलों में, बिल्ड सिस्टम में किए गए इन बदलावों की वजह से बिल्ड में गड़बड़ी हो सकती है. बिल्ड में गड़बड़ी होने से पहले, तैयारी करने के लिए इस पेज पर दी गई जानकारी का इस्तेमाल करें. साथ ही, गड़बड़ियों को ठीक करने और उनसे बचने के लिए, इस पेज पर दिए गए तरीके अपनाएं.
Dexpreopt, Java लाइब्रेरी और ऐप्लिकेशन के AOT कंपाइलेशन की प्रोसेस है. Dexpreopt, बिल्ड प्रोसेस में लगने वाले समय के दौरान होस्ट पर होता है. वहीं, dexopt, जो उपयोगकर्ता के डिवाइस पर होता है. किसी Java मॉड्यूल (लाइब्रेरी या ऐप्लिकेशन) में इस्तेमाल की गई, शेयर की गई लाइब्रेरी डिपेंडेंसी के स्ट्रक्चर को उसका क्लास लोडर कॉन्टेक्स्ट (सीएलसी) कहा जाता है. Dexpreopt की प्रोसेस सही तरीके से हो, इसके लिए ज़रूरी है कि बिल्ड-टाइम और रन-टाइम सीएलसी एक जैसे हों. बिल्ड-टाइम सीएलसी, dexpreopt के दौरान dex2oat कंपाइलर इस्तेमाल करता है. इसे ODEX फ़ाइलों में रिकॉर्ड किया जाता है. वहीं, रन-टाइम सीएलसी वह कॉन्टेक्स्ट है जिसमें पहले से कंपाइल किया गया कोड, डिवाइस पर लोड होता है.
बिल्ड-टाइम और रन-टाइम सीएलसी एक जैसे होने चाहिए. ऐसा इसलिए, क्योंकि इससे कोड सही तरीके से काम करता है और परफ़ॉर्मेंस भी बेहतर होती है. कोड सही तरीके से काम करे, इसके लिए डुप्लीकेट क्लास को हैंडल करना ज़रूरी है. अगर रनटाइम में, शेयर की गई लाइब्रेरी डिपेंडेंसी, कंपाइलेशन के लिए इस्तेमाल की गई डिपेंडेंसी से अलग हैं, तो कुछ क्लास अलग-अलग तरीके से रिज़ॉल्व हो सकती हैं. इससे रनटाइम में मामूली गड़बड़ियां हो सकती हैं. डुप्लीकेट क्लास के लिए रनटाइम में की जाने वाली जांचों से परफ़ॉर्मेंस पर भी असर पड़ता है.
इस्तेमाल के वे उदाहरण जिन पर असर पड़ा है
पहले बूट पर, इन बदलावों का असर पड़ता है. अगर ART को बिल्ड-टाइम और रन-टाइम सीएलसी के बीच कोई अंतर दिखता है, तो वह dexpreopt आर्टफ़ैक्ट को अस्वीकार कर देता है. इसके बजाय, dexopt की प्रोसेस शुरू करता है. इसके बाद के बूट के लिए, यह ठीक है, क्योंकि ऐप्लिकेशन को बैकग्राउंड में dexopt किया जा सकता है और डिस्क पर सेव किया जा सकता है.
Android के वे हिस्से जिन पर असर पड़ा है
इससे उन सभी Java ऐप्लिकेशन और लाइब्रेरी पर असर पड़ता है जिनमें रनटाइम डिपेंडेंसी, अन्य Java लाइब्रेरी पर होती हैं. Android में हज़ारों ऐप्लिकेशन हैं. इनमें से सैकड़ों ऐप्लिकेशन, शेयर की गई लाइब्रेरी का इस्तेमाल करते हैं. पार्टनर पर भी इसका असर पड़ता है, क्योंकि उनकी अपनी लाइब्रेरी और ऐप्लिकेशन होते हैं.
नुकसान पहुंचा सकने वाले बदलाव
बिल्ड सिस्टम को <uses-library> डिपेंडेंसी के बारे में पता होना चाहिए. इसके बाद ही, वह dexpreopt बिल्ड के नियम जनरेट करता है. हालांकि, वह मेनिफ़ेस्ट को सीधे तौर पर ऐक्सेस नहीं कर सकता
और उसमें मौजूद <uses-library>
टैग को नहीं पढ़ सकता. ऐसा इसलिए, क्योंकि बिल्ड सिस्टम को बिल्ड के नियम जनरेट करते समय, किसी भी फ़ाइल को पढ़ने की अनुमति नहीं होती. ऐसा परफ़ॉर्मेंस की वजह से किया जाता है. इसके अलावा, हो सकता है कि मेनिफ़ेस्ट को किसी APK या पहले से बने मॉड्यूल में पैकेज किया गया हो. इसलिए, <uses-library>
जानकारी, बिल्ड फ़ाइलों (Android.bp या Android.mk) में मौजूद होनी चाहिए.
पहले ART, एक ऐसे समाधान का इस्तेमाल करता था जिससे शेयर की गई लाइब्रेरी डिपेंडेंसी को अनदेखा किया जाता था. इसे
&-classpath कहा जाता है. यह सुरक्षित नहीं था और इससे मामूली गड़बड़ियां होती थीं. इसलिए, Android 12 में इस समाधान को
हटा दिया गया है.
नतीजतन, ऐसे Java मॉड्यूल जिनकी बिल्ड फ़ाइलों में <uses-library>
की सही जानकारी नहीं होती है, उनकी वजह से बिल्ड में गड़बड़ी हो सकती है. यह गड़बड़ी, बिल्ड-टाइम सीएलसी के मेल न खाने की वजह से होती है. इसके अलावा, पहले बूट में रिग्रेशन हो सकता है. यह गड़बड़ी, बूट-टाइम
सीएलसी के मेल न खाने और उसके बाद dexopt की प्रोसेस शुरू होने की वजह से होती है.
डेटा को दूसरी जगह भेजने का तरीका
बिल्ड में हुई गड़बड़ी को ठीक करने के लिए, यह तरीका अपनाएं:
किसी खास प्रॉडक्ट के लिए, बिल्ड-टाइम की जांच को पूरी तरह से बंद करने के लिए, प्रॉडक्ट की मेकफ़ाइल में
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := trueसेट करें. इससे बिल्ड से जुड़ी गड़बड़ियां ठीक हो जाती हैं. हालांकि, कुछ खास मामलों में गड़बड़ियां ठीक नहीं होतीं. इन मामलों के बारे में, गड़बड़ियां ठीक करना सेक्शन में बताया गया है. हालांकि, यह एक अस्थायी समाधान है. इससे बूट-टाइम सीएलसी के मेल न खाने और उसके बाद dexopt की प्रोसेस शुरू होने की गड़बड़ी हो सकती है.
बिल्ड-टाइम की जांच को पूरी तरह से बंद करने से पहले, जिन मॉड्यूल में गड़बड़ी हुई थी उन्हें ठीक करें. इसके लिए, उनकी बिल्ड फ़ाइलों में ज़रूरी
<uses-library>जानकारी जोड़ें (ज़्यादा जानकारी के लिए, गड़बड़ियां ठीक करना लेख पढ़ें). ज़्यादातर मॉड्यूल के लिए,Android.bpयाAndroid.mkमें कुछ लाइनें जोड़ने की ज़रूरत होती है.जिन मामलों में गड़बड़ी हो रही है उनके लिए, हर मॉड्यूल के हिसाब से बिल्ड-टाइम की जांच और dexpreopt को बंद करें. dexpreopt को बंद करें, ताकि बिल्ड प्रोसेस में लगने वाला समय और स्टोरेज बर्बाद न हो. ऐसा इसलिए, क्योंकि बूट के दौरान आर्टफ़ैक्ट अस्वीकार कर दिए जाते हैं.
बिल्ड-टाइम की जांच को पूरी तरह से फिर से चालू करने के लिए, पहले चरण में सेट की गई
PRODUCT_BROKEN_VERIFY_USES_LIBRARIESको अनसेट करें. इस बदलाव के बाद, बिल्ड में गड़बड़ी नहीं होनी चाहिए. ऐसा दूसरे और तीसरे चरण की वजह से होता है.तीसरे चरण में बंद किए गए मॉड्यूल को एक-एक करके ठीक करें. इसके बाद, dexpreopt और
<uses-library>की जांच को फिर से चालू करें. ज़रूरत पड़ने पर, गड़बड़ियों की रिपोर्ट दर्ज करें.
Android 12 में, बिल्ड-टाइम <uses-library> की जांच लागू की जाती है.
गड़बड़ियां ठीक करना
इन सेक्शन में, अलग-अलग तरह की गड़बड़ियों को ठीक करने का तरीका बताया गया है.
बिल्ड में गड़बड़ी: सीएलसी मेल नहीं खा रहा है
बिल्ड सिस्टम, 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 में dex2oat कंपाइलर फ़िल्टर कोverifyपर डाउनग्रेड कर देता है. इससे इस मॉड्यूल के लिए, AOT-कंपाइलेशन पूरी तरह से बंद हो जाता है. - कमांड लाइन से, पूरी तरह से गड़बड़ी ठीक करने के लिए, एनवायरमेंट वैरिएबल
RELAX_USES_LIBRARY_CHECK=trueका इस्तेमाल करें. इसका असर,PRODUCT_BROKEN_VERIFY_USES_LIBRARIESके जैसा ही होता है. हालांकि, इसका इस्तेमाल कमांड लाइन पर किया जाता है. एनवायरमेंट वैरिएबल, प्रॉडक्ट वैरिएबल को बदल देता है. - गड़बड़ी की असल वजह को ठीक करने के लिए, बिल्ड सिस्टम को मेनिफ़ेस्ट में मौजूद
<uses-library>टैग के बारे में बताएं. गड़बड़ी के मैसेज की जांच करने से पता चलता है कि किन लाइब्रेरी की वजह से गड़बड़ी हुई है. इसके लिए, की जांच करें या किसी ऐसे APK में मौजूद मेनिफ़ेस्ट की जांच करें जिसे की मदद से जांचा जा सकता है.AndroidManifest.xmlaapt dump badging $APK | grep uses-library
Android.bp मॉड्यूल के लिए:
मॉड्यूल की
libsप्रॉपर्टी में, वह लाइब्रेरी ढूंढें जो मौजूद नहीं है. अगर वह लाइब्रेरी मौजूद है, तो Soong आम तौर पर ऐसी लाइब्रेरी को अपने-आप जोड़ देता है. हालांकि, इन खास मामलों में ऐसा नहीं होता:- लाइब्रेरी, एसडीके लाइब्रेरी नहीं है. इसे
java_sdk_libraryके बजायjava_libraryके तौर पर तय किया गया है. - लाइब्रेरी का नाम (मेनिफ़ेस्ट में), उसके मॉड्यूल के नाम (बिल्ड सिस्टम में) से अलग है.
इसे अस्थायी तौर पर ठीक करने के लिए,
provides_uses_lib: "<library-name>"लाइब्रेरी की डेफ़िनिशन मेंAndroid.bpजोड़ें. लंबे समय तक के लिए, असल समस्या को ठीक करें. इसके लिए, लाइब्रेरी को एसडीके लाइब्रेरी में बदलें या उसके मॉड्यूल का नाम बदलें.- लाइब्रेरी, एसडीके लाइब्रेरी नहीं है. इसे
अगर पिछले चरण से समस्या हल नहीं हुई है, तो ज़रूरी लाइब्रेरी के लिए
uses_libs: ["<library-module-name>"]या वैकल्पिक लाइब्रेरी के लिएoptional_uses_libs: ["<library-module-name>"]मॉड्यूल कीAndroid.bpडेफ़िनिशन में जोड़ें. इन प्रॉपर्टी में, मॉड्यूल के नामों की सूची शामिल की जा सकती है. सूची में लाइब्रेरी का क्रम, मेनिफ़ेस्ट में मौजूद क्रम के जैसा होना चाहिए.
Android.mk मॉड्यूल के लिए:
जांच करें कि लाइब्रेरी का नाम (मेनिफ़ेस्ट में), उसके मॉड्यूल के नाम (बिल्ड सिस्टम में) से अलग है या नहीं. अगर ऐसा है, तो इसे अस्थायी तौर पर ठीक करने के लिए,
LOCAL_PROVIDES_USES_LIBRARY := <library-name>लाइब्रेरी कीAndroid.mkफ़ाइल में जोड़ें. इसके अलावा, लाइब्रेरी कीAndroid.bpफ़ाइल मेंprovides_uses_lib: "<library-name>"जोड़ें. दोनों ही मामले हो सकते हैं, क्योंकिAndroid.mkमॉड्यूल ,Android.bpलाइब्रेरी पर निर्भर हो सकता है. लंबे समय तक के लिए, असल समस्या को ठीक करें. इसके लिए, लाइब्रेरी मॉड्यूल का नाम बदलें.ज़रूरी लाइब्रेरी के लिए
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 को लोड करता है. बिल्ड सिस्टम, सभी मामलों को हैंडल नहीं करता, क्योंकि बिल्ड के दौरान यह पक्के तौर पर नहीं कहा जा सकता कि रनटाइम में ऐप्लिकेशन क्या लोड करेगा.
क्लास लोडर कॉन्टेक्स्ट
सीएलसी, ट्री जैसा स्ट्रक्चर है. यह क्लास-लोडर के क्रम के बारे में बताता है. बिल्ड सिस्टम, सीएलसी का इस्तेमाल सीमित तौर पर करता है. यह सिर्फ़ लाइब्रेरी को कवर करता है, न कि APK या
कस्टम-क्लास लोडर को. यह लाइब्रेरी का एक ट्री है, जो किसी लाइब्रेरी या ऐप्लिकेशन की सभी <uses-library> डिपेंडेंसी के ट्रांज़िटिव
क्लोज़र को दिखाता है. सीएलसी के टॉपलेवल
एलिमेंट, मेनिफ़ेस्ट (क्लाथपाथ) में तय की गई डायरेक्ट <uses-library> डिपेंडेंसी होती हैं. सीएलसी ट्री का हर नोड,
<uses-library> नोड होता है. इसमें अपने <uses-library> सब-नोड हो सकते हैं.
<uses-library> डिपेंडेंसी, डायरेक्टेड एसाइक्लिक ग्राफ़ होती हैं. यह ज़रूरी नहीं है कि यह ट्री हो. इसलिए, सीएलसी में एक ही लाइब्रेरी के लिए कई सबट्री हो सकते हैं. दूसरे शब्दों में, सीएलसी, डिपेंडेंसी ग्राफ़ है जिसे ट्री में "अनफ़ोल्ड" किया गया है. डुप्लीकेशन सिर्फ़ लॉजिकल लेवल पर होता है. असल में, पहले से मौजूद क्लास लोडर डुप्लीकेट नहीं होते. रनटाइम में, हर लाइब्रेरी के लिए एक क्लास लोडर इंस्टेंस होता है.
सीएलसी, लाइब्रेरी या ऐप्लिकेशन में इस्तेमाल की गई Java क्लास को रिज़ॉल्व करते समय, लाइब्रेरी के लुकअप ऑर्डर को तय करता है. लुकअप ऑर्डर ज़रूरी है, क्योंकि लाइब्रेरी में डुप्लीकेट क्लास हो सकती हैं. क्लास को पहले मैच के हिसाब से रिज़ॉल्व किया जाता है.
डिवाइस पर (रन-टाइम) सीएलसी
PackageManager (frameworks/base में मौजूद), उपयोगकर्ता के डिवाइस पर Java मॉड्यूल लोड करने के लिए सीएलसी बनाता है. यह मॉड्यूल के
मेनिफ़ेस्ट में मौजूद <uses-library> टैग में शामिल लाइब्रेरी को, टॉप-लेवल सीएलसी एलिमेंट के तौर पर जोड़ता है.
इस्तेमाल की गई हर लाइब्रेरी के लिए, PackageManager उसकी सभी <uses-library>
डिपेंडेंसी (उस लाइब्रेरी के मेनिफ़ेस्ट में टैग के तौर पर तय की गई) को हासिल करता है. साथ ही, हर डिपेंडेंसी के लिए
नेस्टेड सीएलसी जोड़ता है. यह प्रोसेस, सीएलसी ट्री के सभी
लीफ़ नोड, <uses-library>
डिपेंडेंसी के बिना लाइब्रेरी होने तक, बार-बार चलती है.
PackageManager को सिर्फ़ शेयर की गई लाइब्रेरी के बारे में पता होता है. इस इस्तेमाल में, शेयर की गई लाइब्रेरी की डेफ़िनिशन, इसके सामान्य मतलब (जैसे, शेयर की गई बनाम स्टैटिक) से अलग होती है. Android में,
Java की शेयर की गई लाइब्रेरी वे होती हैं जो डिवाइस पर इंस्टॉल किए गए XML कॉन्फ़िग (/system/etc/permissions/platform.xml) में शामिल होती हैं.
हर एंट्री में, शेयर की गई लाइब्रेरी का नाम,
उसकी DEX jar फ़ाइल का पाथ, और डिपेंडेंसी की सूची शामिल होती है.
इस सूची में, रनटाइम में इस्तेमाल की जाने वाली अन्य शेयर की गई लाइब्रेरी और उसके मेनिफ़ेस्ट में
<uses-library> टैग में तय की गई डिपेंडेंसी शामिल होती हैं.
दूसरे शब्दों में, जानकारी के दो सोर्स होते हैं. इनकी मदद से, PackageManager
रनटाइम में सीएलसी बनाता है. ये सोर्स हैं: मेनिफ़ेस्ट में मौजूद <uses-library> टैग और
XML कॉन्फ़िग में शेयर की गई लाइब्रेरी डिपेंडेंसी.
होस्ट पर (बिल्ड-टाइम) सीएलसी
सीएलसी की ज़रूरत सिर्फ़ लाइब्रेरी या ऐप्लिकेशन लोड करते समय नहीं होती, बल्कि कंपाइल करते समय भी होती है. कंपाइलेशन, डिवाइस पर (dexopt) या बिल्ड के दौरान (dexpreopt) हो सकता है. चूंकि dexopt, उपयोगकर्ता के डिवाइस पर होता है, इसलिए इसके पास वही जानकारी होती है जो PackageManager के पास होती है. जैसे, मेनिफ़ेस्ट और शेयर की गई लाइब्रेरी डिपेंडेंसी.
हालांकि, dexpreopt, होस्ट पर और पूरी तरह से अलग एनवायरमेंट में होता है. इसे बिल्ड सिस्टम से वही जानकारी हासिल करनी होती है.
इसलिए, dexpreopt में इस्तेमाल किया गया बिल्ड-टाइम सीएलसी और PackageManager में इस्तेमाल किया गया रन-टाइम सीएलसी एक ही होता है. हालांकि, इसे दो अलग-अलग तरीकों से कंप्यूट किया जाता है.
बिल्ड-टाइम और रन-टाइम सीएलसी एक जैसे होने चाहिए. ऐसा न होने पर, dexpreopt से बनाया गया AOT-कंपाइल किया गया कोड अस्वीकार कर दिया जाता है. बिल्ड-टाइम और रन-टाइम सीएलसी की समानता की जांच करने के लिए, dex2oat कंपाइलर, बिल्ड-टाइम सीएलसी को *.odex फ़ाइलों में रिकॉर्ड करता है. यह जानकारी, OAT फ़ाइल हेडर के classpath फ़ील्ड में होती है. सेव किया गया सीएलसी ढूंढने के लिए, यह कमांड इस्तेमाल करें:
oatdump --oat-file=<FILE> | grep '^classpath = '
बूट के दौरान, logcat में बिल्ड-टाइम और रन-टाइम सीएलसी के मेल न खाने की गड़बड़ी की रिपोर्ट की जाती है. इसे ढूंढने के लिए, यह कमांड इस्तेमाल करें:
logcat | grep -E 'ClassLoaderContext [a-z ]+ mismatch'
सीएलसी के मेल न खाने की गड़बड़ी से परफ़ॉर्मेंस पर बुरा असर पड़ता है. ऐसा इसलिए, क्योंकि इससे लाइब्रेरी या ऐप्लिकेशन को dexopt करना पड़ता है या ऑप्टिमाइज़ेशन के बिना चलाना पड़ता है. उदाहरण के लिए, ऐप्लिकेशन के कोड को APK से मेमोरी में एक्सट्रैक्ट करना पड़ सकता है. यह एक महंगा ऑपरेशन है.
शेयर की गई लाइब्रेरी, वैकल्पिक या ज़रूरी हो सकती है. dexpreopt के हिसाब से, ज़रूरी लाइब्रेरी, बिल्ड प्रोसेस में लगने वाले समय के दौरान मौजूद होनी चाहिए. इसके मौजूद न होने पर, बिल्ड में गड़बड़ी होती है. वैकल्पिक लाइब्रेरी, बिल्ड प्रोसेस में लगने वाले समय के दौरान मौजूद हो भी सकती है और नहीं भी. अगर यह मौजूद है, तो इसे सीएलसी में जोड़ा जाता है, dex2oat को पास किया जाता है, और *.odex फ़ाइल में रिकॉर्ड किया जाता है. अगर कोई वैकल्पिक लाइब्रेरी मौजूद नहीं है, तो उसे छोड़ दिया जाता है और सीएलसी में नहीं जोड़ा जाता. अगर बिल्ड-टाइम और रन-टाइम स्टेटस में कोई अंतर है, जैसे कि वैकल्पिक लाइब्रेरी एक मामले में मौजूद है, लेकिन दूसरे में नहीं, तो बिल्ड-टाइम और रन-टाइम सीएलसी मेल नहीं खाते. साथ ही, कंपाइल किया गया कोड अस्वीकार कर दिया जाता है.
बिल्ड सिस्टम की ऐडवांस जानकारी (मेनिफ़ेस्ट फ़िक्सर)
कभी-कभी, किसी लाइब्रेरी या ऐप्लिकेशन के सोर्स मेनिफ़ेस्ट में <uses-library> टैग मौजूद नहीं होते हैं. ऐसा तब हो सकता है, जब लाइब्रेरी या ऐप्लिकेशन की ट्रांज़िटिव डिपेंडेंसी में से कोई एक, किसी दूसरे <uses-library> टैग का इस्तेमाल करना शुरू कर दे. साथ ही, लाइब्रेरी या ऐप्लिकेशन के मेनिफ़ेस्ट को अपडेट न किया जाए, ताकि उसमें वह टैग शामिल हो सके.
Soong, किसी लाइब्रेरी
या ऐप्लिकेशन के लिए, कुछ ऐसे <uses-library> टैग को अपने-आप कंप्यूट कर सकता है जो मौजूद नहीं हैं. ऐसा, लाइब्रेरी या ऐप्लिकेशन के ट्रांज़िटिव डिपेंडेंसी क्लोज़र
में मौजूद एसडीके लाइब्रेरी के तौर पर किया जाता है. क्लोज़र की ज़रूरत इसलिए होती है, क्योंकि लाइब्रेरी (या ऐप्लिकेशन) किसी ऐसी स्टैटिक लाइब्रेरी पर निर्भर हो सकता है जो एसडीके लाइब्रेरी पर निर्भर है. साथ ही, यह किसी दूसरी लाइब्रेरी के ज़रिए ट्रांज़िटिव तौर पर फिर से निर्भर हो सकता है.
सभी <uses-library> टैग को इस तरह कंप्यूट नहीं किया जा सकता. हालांकि, जब ऐसा किया जा सकता है, तो Soong को मेनिफ़ेस्ट एंट्री अपने-आप जोड़ने देना बेहतर होता है. इससे गड़बड़ी होने की संभावना कम होती है और रखरखाव आसान हो जाता है. उदाहरण के लिए, जब कई ऐप्लिकेशन, किसी ऐसी स्टैटिक
लाइब्रेरी का इस्तेमाल करते हैं जो नई <uses-library> डिपेंडेंसी जोड़ती है, तो सभी ऐप्लिकेशन को अपडेट करना ज़रूरी होता है.
इसका रखरखाव करना मुश्किल होता है.