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 में या पहले से बने हुए
में पैकेज किया गया हो. इसलिए, बिल्ड फ़ाइलों (Android.bp
या Android.mk
) में <uses-library>
की जानकारी मौजूद होनी चाहिए.
पहले ART, शेयर की गई लाइब्रेरी की डिपेंडेंसी (जिन्हें &-classpath
कहा जाता है) को अनदेखा करने वाले तरीके का इस्तेमाल करता था. यह तरीका असुरक्षित था और इससे छोटे-मोटे गड़बड़ियां होती थीं. इसलिए, Android 12 में इस तरीके को हटा दिया गया था.
इस वजह से, जिन Java मॉड्यूल की बिल्ड फ़ाइलों में <uses-library>
की सही जानकारी नहीं होती है उनसे बिल्ड में रुकावट (बिल्ड के समय CLC के मेल न खाने की वजह से) या पहली बार बूट होने में लगने वाले समय में बढ़ोतरी (बूट के समय CLC के मेल न खाने और उसके बाद dexopt की वजह से) हो सकती है.
माइग्रेशन पाथ
टूटे हुए बिल्ड को ठीक करने के लिए यह तरीका अपनाएं:
किसी प्रॉडक्ट के लिए, बिल्ड-टाइम की जांच की सुविधा को दुनिया भर में बंद करें. इसके लिए,
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
में मौजूद है. इससे बिल्ड से जुड़ी गड़बड़ियां ठीक हो जाती हैं (कुछ खास मामलों को छोड़कर, जो ब्रेकेज ठीक करना सेक्शन में दिए गए हैं). हालांकि, यह समस्या कुछ समय के लिए है. इसकी वजह से, बूट-टाइम के सीएलसी में अंतर हो सकता है. इसके बाद, डेक्सप्ट की वजह से हो सकता है.
उन मॉड्यूल को ठीक करें जो वैश्विक स्तर पर बिल्ड-टाइम जांच की सुविधा को बंद करने से पहले बंद हो गए थे. इसके लिए, उनकी बिल्ड फ़ाइलों में
<uses-library>
से जुड़ी ज़रूरी जानकारी जोड़ें (ज़्यादा जानकारी के लिए, ब्रेकेज ठीक करना देखें). ज़्यादातर मॉड्यूल के लिए,Android.bp
याAndroid.mk
में कुछ लाइनें जोड़नी पड़ती हैं.हर मॉड्यूल के हिसाब से, समस्या वाले मामलों के लिए बिल्ड-टाइम की जांच और डीएक्सपेक्ट को बंद करें. dexpreopt को बंद करें, ताकि बूट होने पर अस्वीकार किए जाने वाले आर्टफ़ैक्ट का समय और स्टोरेज बर्बाद न हो.
पहले चरण में सेट किए गए
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES
को हटाकर, बिल्ड के समय की जांच को फिर से चालू करें. इस बदलाव के बाद, बिल्ड की प्रोसेस में रुकावट नहीं आनी चाहिए. ऐसा दूसरे और तीसरे चरण की वजह से होता है.आपने तीसरे चरण में एक-एक करके जिन मॉड्यूल को बंद किया था उन्हें ठीक करें. इसके बाद, 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
सेट करें. बिल्ड-टाइम की जांच अब भी की जा रही है. हालांकि, जांच न होने का मतलब यह नहीं है कि बिल्ड फ़ेल हो गया. इसके बजाय, जांच में गड़बड़ी होने पर बिल्ड सिस्टम, dexreopt में 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
के तौर पर दिखाया गया है. - लाइब्रेरी का नाम (मैनिफ़ेस्ट में) इसके मॉड्यूल नाम (बिल्ड सिस्टम में) से अलग है.
इसे कुछ समय के लिए ठीक करने के लिए,
Android.bp
लाइब्रेरी की परिभाषा मेंprovides_uses_lib: "<library-name>"
जोड़ें. लंबे समय तक समस्या से बचने के लिए, लाइब्रेरी में मौजूद समस्या को ठीक करें: लाइब्रेरी को SDK टूल की लाइब्रेरी में बदलें या उसके मॉड्यूल का नाम बदलें.- लाइब्रेरी, एसडीके लाइब्रेरी नहीं है. इसे
अगर पिछले चरण में रिज़ॉल्यूशन नहीं दिया गया था, तो ज़रूरी लाइब्रेरी के लिए
uses_libs: ["<library-module-name>"]
या वैकल्पिक लाइब्रेरी के लिए मॉड्यूल कीAndroid.bp
परिभाषा में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
बूट-टाइम सीएलसी मेल नहीं खाता
पहली बार बूट करने पर, सीएलसी के मेल न खाने वाले मैसेज के लिए 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 क्लास को हल करते समय, सीएलसी लाइब्रेरी के लुकअप ऑर्डर तय करता है. लुकअप ऑर्डर ज़रूरी है, क्योंकि लाइब्रेरी में डुप्लीकेट क्लास हो सकती हैं और क्लास को पहले मैच के हिसाब से हल किया जाता है.
डिवाइस पर (रन-टाइम) सीएलसी
डिवाइस पर Java मॉड्यूल लोड करने के लिए, PackageManager
(frameworks/base
में) एक सीएलसी बनाता है. यह मॉड्यूल के मैनिफ़ेस्ट में, <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>
डिपेंडेंसी जोड़ती है, तो सभी ऐप्लिकेशन को अपडेट करना ज़रूरी होता है. इसे मैनेज करना मुश्किल होता है.