Android 12 में, DEX फ़ाइलों (dexpreopt) के एओटी कंपाइलेशन के लिए, बिल्ड सिस्टम में बदलाव किए गए हैं. ये बदलाव, उन Java मॉड्यूल के लिए किए गए हैं जिनमें <uses-library>
डिपेंडेंसी मौजूद हैं. कुछ मामलों में, बिल्ड सिस्टम में किए गए ये बदलाव, बिल्ड को बंद कर सकते हैं. इस पेज का इस्तेमाल करके, रुकावटों से जुड़ी तैयारी करें. साथ ही, उन्हें ठीक करने और कम करने के लिए, इस पेज पर दी गई सलाह अपनाएं.
Dexpreopt, Java लाइब्रेरी और ऐप्लिकेशन को पहले से कंपाइल करने की प्रोसेस है. Dexpreopt, बिल्ड के समय होस्ट पर होता है. इसके उलट, dexopt, डिवाइस पर होता है. किसी Java मॉड्यूल (लाइब्रेरी या ऐप्लिकेशन) में इस्तेमाल की जाने वाली शेयर की गई लाइब्रेरी डिपेंडेंसी का स्ट्रक्चर, क्लास लोडर कॉन्टेक्स्ट (सीएलसी) कहलाता है. dexpreopt के सही होने की पुष्टि करने के लिए, बिल्ड टाइम और रन टाइम सीएलसी एक जैसे होने चाहिए. बिल्ड टाइम सीएलसी वह है जिसका इस्तेमाल dex2oat कंपाइलर, dexpreopt के समय करता है (इसे ODEX फ़ाइलों में रिकॉर्ड किया जाता है). वहीं, रन-टाइम सीएलसी वह कॉन्टेक्स्ट है जिसमें डिवाइस पर पहले से कंपाइल किया गया कोड लोड किया जाता है.
सही होने और परफ़ॉर्मेंस, दोनों के लिए यह ज़रूरी है कि बिल्ड टाइम और रन टाइम के सीएलसी एक जैसे हों. सही जानकारी देने के लिए, डुप्लीकेट क्लास को मैनेज करना ज़रूरी है. अगर रनटाइम के दौरान शेयर की गई लाइब्रेरी की डिपेंडेंसी, संकलन के लिए इस्तेमाल की गई डिपेंडेंसी से अलग हैं, तो हो सकता है कि कुछ क्लास अलग तरीके से रिज़ॉल्व हों. इससे रनटाइम के दौरान छोटे-मोटे गड़बड़ियां हो सकती हैं. डुप्लीकेट क्लास के लिए रनटाइम की जांच करने से भी परफ़ॉर्मेंस पर असर पड़ता है.
इस्तेमाल के ऐसे उदाहरण जिन पर असर पड़ा है
इन बदलावों का असर, मुख्य रूप से पहले बूट पर पड़ता है: अगर ART को बिल्ड टाइम और रन टाइम सीएलसी के बीच कोई अंतर मिलता है, तो वह dexpreopt आर्टफ़ैक्ट को अस्वीकार कर देता है और इसके बजाय dexopt को चलाता है. डिवाइस को फिर से चालू करने पर, यह समस्या नहीं होती. ऐसा इसलिए, क्योंकि ऐप्लिकेशन को बैकग्राउंड में डीएक्सप्ट किया जा सकता है और डिस्क पर सेव किया जा सकता है.
Android के जिन हिस्सों पर असर पड़ा है
इससे उन सभी Java ऐप्लिकेशन और लाइब्रेरी पर असर पड़ता है जिनमें रनटाइम के दौरान, दूसरी Java लाइब्रेरी पर निर्भरता होती है. Android पर हज़ारों ऐप्लिकेशन मौजूद हैं और उनमें से सैकड़ों ऐप्लिकेशन, शेयर की गई लाइब्रेरी का इस्तेमाल करते हैं. पार्टनर पर भी इसका असर पड़ता है, क्योंकि उनके पास अपनी लाइब्रेरी और ऐप्लिकेशन होते हैं.
बदलावों को अलग-अलग करना
dexpreopt के लिए बने बिल्ड नियम जनरेट करने से पहले, बिल्ड सिस्टम को <uses-library>
की डिपेंडेंसी के बारे में पता होना चाहिए. हालांकि, यह सीधे तौर पर मेनिफ़ेस्ट को ऐक्सेस नहीं कर सकता और उसमें मौजूद <uses-library>
टैग को नहीं पढ़ सकता. इसकी वजह यह है कि परफ़ॉर्मेंस से जुड़ी वजहों से, बिल्ड सिस्टम को बिल्ड नियम जनरेट करते समय, अपनी पसंद के मुताबिक फ़ाइलें पढ़ने की अनुमति नहीं होती. इसके अलावा, मेनिफ़ेस्ट को 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>
जानकारी जोड़ें. ज़्यादा जानकारी के लिए, गड़बड़ियों को ठीक करना लेख पढ़ें. ज़्यादातर मॉड्यूल के लिए,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>
टैग के बारे में बताएं. गड़बड़ी के मैसेज की जांच करने से पता चलता है कि कौनसी लाइब्रेरी इस समस्या की वजह है. इसके अलावा,AndroidManifest.xml
या APK में मौजूद मेनिफ़ेस्ट की जांच करने से भी यह पता चलता है. मेनिफ़ेस्ट की जांच, `aapt dump badging $APK | grep uses-library
` की मदद से की जा सकती है.
Android.bp
मॉड्यूल के लिए:
मॉड्यूल की
libs
प्रॉपर्टी में, लाइब्रेरी ढूंढें. अगर यह मौजूद है, तो Soong आम तौर पर ऐसी लाइब्रेरी अपने-आप जोड़ देता है. हालांकि, इन खास मामलों में ऐसा नहीं होता:- लाइब्रेरी, एसडीके लाइब्रेरी नहीं है. इसे
java_sdk_library
के बजायjava_library
के तौर पर दिखाया गया है. - लाइब्रेरी का नाम (मैनफ़ेस्ट में) और मॉड्यूल का नाम (बिल्ड सिस्टम में) अलग-अलग है.
इसे कुछ समय के लिए ठीक करने के लिए, लाइब्रेरी की परिभाषा में
provides_uses_lib: "<library-name>"
जोड़ेंAndroid.bp
. लंबे समय तक समस्या से बचने के लिए, लाइब्रेरी में मौजूद समस्या को ठीक करें: लाइब्रेरी को SDK टूल की लाइब्रेरी में बदलें या उसके मॉड्यूल का नाम बदलें.- लाइब्रेरी, एसडीके लाइब्रेरी नहीं है. इसे
अगर पिछले चरण में समस्या हल नहीं हुई, तो मॉड्यूल की
Android.bp
परिभाषा में, ज़रूरी लाइब्रेरी के लिएuses_libs: ["<library-module-name>"]
या वैकल्पिक लाइब्रेरी के लिएoptional_uses_libs: ["<library-module-name>"]
जोड़ें. ये प्रॉपर्टी, मॉड्यूल के नामों की सूची स्वीकार करती हैं. सूची में लाइब्रेरी का क्रम, मेनिफ़ेस्ट में दिए गए क्रम जैसा होना चाहिए.
Android.mk
मॉड्यूल के लिए:
देखें कि लाइब्रेरी का नाम (मैनफ़ेस्ट में) और मॉड्यूल का नाम (बिल्ड सिस्टम में) अलग-अलग है या नहीं. अगर ऐसा होता है, तो लाइब्रेरी की
Android.mk
फ़ाइल मेंLOCAL_PROVIDES_USES_LIBRARY := <library-name>
जोड़कर या लाइब्रेरी कीAndroid.bp
फ़ाइल मेंprovides_uses_lib: "<library-name>"
जोड़कर, इसे कुछ समय के लिए ठीक करें. दोनों ही मामले संभव हैं, क्योंकिAndroid.mk
मॉड्यूल,Android.bp
लाइब्रेरी पर निर्भर हो सकता है. लंबे समय तक इस समस्या से बचने के लिए, लाइब्रेरी मॉड्यूल का नाम बदलें.ज़रूरी लाइब्रेरी के लिए
LOCAL_USES_LIBRARIES := <library-module-name>
जोड़ें. साथ ही, मॉड्यूल कीAndroid.mk
डेफ़िनिशन में वैकल्पिक लाइब्रेरी के लिएLOCAL_OPTIONAL_USES_LIBRARIES := <library-module-name>
जोड़ें. ये प्रॉपर्टी, मॉड्यूल के नामों की सूची स्वीकार करती हैं. सूची में लाइब्रेरी का क्रम, मेनिफ़ेस्ट में दिए गए क्रम जैसा होना चाहिए.
बिल्ड करने में गड़बड़ी: लाइब्रेरी का पाथ अज्ञात है
अगर बिल्ड सिस्टम को <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 के मेनिफ़ेस्ट से, Y के लिए बनाई गई बिल्ड फ़ाइल में <uses-library>
X को जोड़ने की कोशिश करने पर, बिल्ड करने में गड़बड़ी हो सकती है. इसकी वजह यह है कि 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
बूट के समय सीएलसी मेल नहीं खाता
पहली बार बूट करने पर, 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: ...
अगर आपको सीएलसी मेल न खाने की चेतावनी मिलती है, तो गड़बड़ी वाले मॉड्यूल के लिए 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 में, डिवाइस पर इंस्टॉल की गई (/system/etc/permissions/platform.xml
) एक्सएमएल कॉन्फ़िगरेशन में मौजूद, Java की शेयर की गई लाइब्रेरी को शेयर की गई लाइब्रेरी कहा जाता है. हर एंट्री में, शेयर की गई लाइब्रेरी का नाम, उसकी DEX jar फ़ाइल का पाथ, और डिपेंडेंसी की सूची होती है. डिपेंडेंसी, ऐसी अन्य शेयर की गई लाइब्रेरी होती हैं जिनका इस्तेमाल, रनटाइम के दौरान किया जाता है. साथ ही, इनके बारे में मेनिफ़ेस्ट में <uses-library>
टैग में बताया जाता है.
दूसरे शब्दों में, जानकारी के दो सोर्स हैं जिनकी मदद से PackageManager
, रनटाइम के दौरान सीएलसी बना सकता है: मेनिफ़ेस्ट में <uses-library>
टैग और एक्सएमएल कॉन्फ़िगरेशन में शेयर की गई लाइब्रेरी की डिपेंडेंसी.
होस्ट पर (बिल्ड के समय) सीएलसी
लाइब्रेरी या ऐप्लिकेशन को लोड करने के साथ-साथ, उसे संकलित करने के लिए भी सीएलसी की ज़रूरत होती है. कंपाइलेशन, डिवाइस पर (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'
लाइब्रेरी और ऐप्लिकेशन के वर्शन का मेल न खाने से परफ़ॉर्मेंस पर बुरा असर पड़ता है. ऐसा होने पर, लाइब्रेरी या ऐप्लिकेशन को डिकोड करना पड़ता है या उसे ऑप्टिमाइज़ेशन के बिना चलाना पड़ता है. उदाहरण के लिए, हो सकता है कि ऐप्लिकेशन के कोड को APK से मेमोरी में निकालना पड़े. यह एक बहुत महंगा ऑपरेशन है.
शेयर की गई लाइब्रेरी को ज़रूरी या वैकल्पिक बनाया जा सकता है. dexpreopt के हिसाब से, ज़रूरी लाइब्रेरी बिल्ड के समय मौजूद होनी चाहिए. अगर यह मौजूद नहीं है, तो बिल्ड में गड़बड़ी होती है. बिल्ड के समय, वैकल्पिक लाइब्रेरी मौजूद हो सकती है या नहीं: अगर मौजूद है, तो इसे सीएलसी में जोड़ा जाता है, dex2oat को पास किया जाता है, और *.odex
फ़ाइल में रिकॉर्ड किया जाता है. अगर कोई लाइब्रेरी उपलब्ध नहीं है, तो उसे छोड़ दिया जाता है और सीएलसी में नहीं जोड़ा जाता. अगर बिल्ड टाइम और रन टाइम स्टेटस के बीच कोई मैच नहीं होता है (एक मामले में वैकल्पिक लाइब्रेरी मौजूद है, लेकिन दूसरे में नहीं), तो बिल्ड टाइम और रन टाइम सीएलसी मैच नहीं होते और कंपाइल किया गया कोड अस्वीकार कर दिया जाता है.
बिल्ड सिस्टम की बेहतर जानकारी (मेनिफ़ेस्ट फ़िक्सर)
कभी-कभी, लाइब्रेरी या ऐप्लिकेशन के सोर्स मेनिफ़ेस्ट में <uses-library>
टैग मौजूद नहीं होते. उदाहरण के लिए, ऐसा तब हो सकता है, जब लाइब्रेरी या ऐप्लिकेशन की ट्रांज़िशन डिपेंडेंसी में से कोई एक, किसी दूसरे <uses-library>
टैग का इस्तेमाल शुरू कर दे और लाइब्रेरी या ऐप्लिकेशन के मेनिफ़ेस्ट को उसे शामिल करने के लिए अपडेट न किया गया हो.
Soong, किसी लाइब्रेरी या ऐप्लिकेशन के लिए, छूटे हुए कुछ <uses-library>
टैग का हिसाब अपने-आप लगा सकता है. ऐसा इसलिए, क्योंकि लाइब्रेरी या ऐप्लिकेशन की ट्रांज़िटिव डिपेंडेंसी क्लोज़र में SDK टूल की लाइब्रेरी शामिल होती हैं. क्लोज़र की ज़रूरत इसलिए होती है, क्योंकि लाइब्रेरी (या ऐप्लिकेशन) किसी ऐसी स्टैटिक लाइब्रेरी पर निर्भर हो सकती है जो किसी SDK टूल की लाइब्रेरी पर निर्भर हो. साथ ही, हो सकता है कि वह फिर से किसी दूसरी लाइब्रेरी के ज़रिए ट्रांज़िटिव तौर पर निर्भर हो.
सभी <uses-library>
टैग को इस तरह से कैलकुलेट नहीं किया जा सकता. हालांकि, जब भी संभव हो, Soong को मेनिफ़ेस्ट एंट्री अपने-आप जोड़ने दें. इससे गड़बड़ी की संभावना कम होती है और रखरखाव आसान हो जाता है. उदाहरण के लिए, जब कई ऐप्लिकेशन किसी ऐसी स्टैटिक लाइब्रेरी का इस्तेमाल करते हैं जो नई <uses-library>
डिपेंडेंसी जोड़ती है, तो सभी ऐप्लिकेशन को अपडेट करना ज़रूरी होता है. इसे मैनेज करना मुश्किल होता है.