Dexpreopt এবং <uses-library> চেক

Android 12-এ <uses-library> নির্ভরতা আছে এমন Java মডিউলগুলির জন্য DEX ফাইলের (dexpreopt) AOT সংকলনে সিস্টেম পরিবর্তনগুলি তৈরি করা হয়েছে। কিছু ক্ষেত্রে এই বিল্ড সিস্টেম পরিবর্তন বিল্ড ভেঙ্গে দিতে পারে। ভাঙ্গনের জন্য প্রস্তুত করতে এই পৃষ্ঠাটি ব্যবহার করুন এবং সেগুলিকে ঠিক করতে এবং প্রশমিত করতে এই পৃষ্ঠার রেসিপিগুলি অনুসরণ করুন৷

ডেক্সপ্রিওপ্ট হল জাভা লাইব্রেরি এবং অ্যাপের আগাম সংকলনের প্রক্রিয়া। ডেক্সপ্রিওপ্ট বিল্ড টাইমে অন-হোস্ট হয় ( ডেক্সপট এর বিপরীতে, যা ডিভাইসে ঘটে)। একটি জাভা মডিউল (একটি লাইব্রেরি বা একটি অ্যাপ) দ্বারা ব্যবহৃত শেয়ার্ড লাইব্রেরি নির্ভরতার কাঠামোটি এর ক্লাস লোডার প্রসঙ্গ (CLC) নামে পরিচিত। ডেক্সপ্রিওপ্টের সঠিকতার গ্যারান্টি দিতে, বিল্ড-টাইম এবং রান-টাইম সিএলসি অবশ্যই মিলে যাবে। বিল্ড-টাইম CLC হল যা dex2oat কম্পাইলার dexpreopt সময়ে ব্যবহার করে (এটি ODEX ফাইলগুলিতে রেকর্ড করা হয়), এবং রান-টাইম CLC হল সেই প্রেক্ষাপট যেখানে প্রি-কম্পাইল করা কোড ডিভাইসে লোড করা হয়।

এই বিল্ড-টাইম এবং রান-টাইম সিএলসি অবশ্যই সঠিকতা এবং কর্মক্ষমতা উভয়ের কারণেই মিলে যাবে। সঠিকতার জন্য, ডুপ্লিকেট ক্লাস পরিচালনা করা প্রয়োজন। রানটাইমে শেয়ার্ড লাইব্রেরি নির্ভরতাগুলি সংকলনের জন্য ব্যবহৃত লাইব্রেরিগুলির থেকে আলাদা হলে, কিছু ক্লাস আলাদাভাবে সমাধান করা যেতে পারে, যার ফলে সূক্ষ্ম রানটাইম বাগগুলি হতে পারে। ডুপ্লিকেট ক্লাসের জন্য রানটাইম চেক দ্বারা কর্মক্ষমতাও প্রভাবিত হয়।

প্রভাবিত ব্যবহারের ক্ষেত্রে

প্রথম বুট হল প্রধান ব্যবহারের ক্ষেত্রে যা এই পরিবর্তনগুলির দ্বারা প্রভাবিত হয়: যদি ART বিল্ড-টাইম এবং রান-টাইম CLC-এর মধ্যে একটি অমিল শনাক্ত করে, তবে এটি dexpreopt আর্টিফ্যাক্টগুলি প্রত্যাখ্যান করে এবং পরিবর্তে dexopt চালায়। পরবর্তী বুটগুলির জন্য এটি ঠিক কারণ অ্যাপগুলিকে ব্যাকগ্রাউন্ডে ডিক্সপ্ট করা যায় এবং ডিস্কে সংরক্ষণ করা যায়।

অ্যান্ড্রয়েডের প্রভাবিত এলাকা

এটি অন্যান্য জাভা লাইব্রেরিতে রানটাইম নির্ভরতা আছে এমন সমস্ত জাভা অ্যাপ এবং লাইব্রেরিকে প্রভাবিত করে। অ্যান্ড্রয়েডের হাজার হাজার অ্যাপ রয়েছে এবং সেগুলির শত শত শেয়ার করা লাইব্রেরি ব্যবহার করে। অংশীদাররাও প্রভাবিত হয়, কারণ তাদের নিজস্ব লাইব্রেরি এবং অ্যাপ রয়েছে।

বিরতি পরিবর্তন

dexpreopt বিল্ড নিয়ম তৈরি করার আগে বিল্ড সিস্টেমকে <uses-library> নির্ভরতা জানতে হবে। যাইহোক, এটি সরাসরি ম্যানিফেস্ট অ্যাক্সেস করতে পারে না এবং এটিতে <uses-library> ট্যাগগুলি পড়তে পারে না, কারণ বিল্ড সিস্টেমটি যখন বিল্ড নিয়ম তৈরি করে (কর্মক্ষমতার কারণে) নির্বিচারে ফাইলগুলি পড়ার অনুমতি দেয় না। তদুপরি, ম্যানিফেস্টটি একটি APK বা পূর্বনির্মাণের ভিতরে প্যাকেজ করা হতে পারে। অতএব, <uses-library> তথ্য অবশ্যই বিল্ড ফাইলগুলিতে উপস্থিত থাকতে হবে ( Android.bp বা Android.mk )।

পূর্বে ART একটি সমাধান ব্যবহার করত যা ভাগ করা লাইব্রেরি নির্ভরতাকে উপেক্ষা করত (যা &-classpath নামে পরিচিত)। এটি অনিরাপদ ছিল এবং সূক্ষ্ম বাগ সৃষ্টি করেছিল, তাই অ্যান্ড্রয়েড 12 এ সমাধানটি সরিয়ে দেওয়া হয়েছিল।

ফলস্বরূপ, জাভা মডিউল যেগুলি তাদের বিল্ড ফাইলগুলিতে সঠিক <uses-library> তথ্য প্রদান করে না সেগুলি বিল্ড ব্রেকেজ (একটি বিল্ড-টাইম CLC অমিলের কারণে) বা প্রথম-বুট টাইম রিগ্রেশন (বুট-টাইম CLC দ্বারা সৃষ্ট) হতে পারে dexopt দ্বারা অনুসৃত অমিল)।

অভিবাসন পথ

একটি ভাঙা বিল্ড ঠিক করতে এই পদক্ষেপগুলি অনুসরণ করুন:

  1. বিশ্বব্যাপী সেট করে একটি নির্দিষ্ট পণ্যের জন্য বিল্ড-টাইম চেক অক্ষম করুন

    PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true

    পণ্যের মেকফাইলে। এটি বিল্ড ত্রুটিগুলি সংশোধন করে (বিশেষ ক্ষেত্রে ছাড়া, ফিক্সিং ব্রেকেজ বিভাগে তালিকাভুক্ত)। যাইহোক, এটি একটি অস্থায়ী সমাধান, এবং এটি dexopt দ্বারা অনুসরণ করে বুট-টাইম CLC অমিল হতে পারে।

  2. আপনার বিল্ড-টাইম চেক বিশ্বব্যাপী অক্ষম করার আগে ব্যর্থ হওয়া মডিউলগুলিকে তাদের বিল্ড ফাইলগুলিতে প্রয়োজনীয় <uses-library> তথ্য যোগ করে ঠিক করুন (বিশদ বিবরণের জন্য বিচ্ছেদের সংশোধন দেখুন)। বেশিরভাগ মডিউলের জন্য এর জন্য Android.bp বা Android.mk এ কয়েকটি লাইন যোগ করা প্রয়োজন।

  3. প্রতি-মডিউল ভিত্তিতে, সমস্যাযুক্ত ক্ষেত্রে বিল্ড-টাইম চেক এবং ডেক্সপ্রিওপ্ট অক্ষম করুন। dexpreopt অক্ষম করুন যাতে আপনি বুট করার সময় প্রত্যাখ্যাত আর্টিফ্যাক্টগুলিতে বিল্ড সময় এবং স্টোরেজ নষ্ট করবেন না।

  4. ধাপ 1 এ সেট করা PRODUCT_BROKEN_VERIFY_USES_LIBRARIES আনসেট করে বিশ্বব্যাপী বিল্ড-টাইম চেক পুনরায়-সক্ষম করুন; এই পরিবর্তনের পরে বিল্ডটি ব্যর্থ হওয়া উচিত নয় (পদক্ষেপ 2 এবং 3 এর কারণে)।

  5. আপনি ধাপ 3-এ অক্ষম করা মডিউলগুলিকে এক সময়ে ঠিক করুন, তারপরে dexpreopt পুনরায় সক্রিয় করুন এবং <uses-library> চেক করুন। প্রয়োজনে বাগ ফাইল করুন।

Android 12-এ বিল্ড-টাইম <uses-library> চেক প্রয়োগ করা হয়েছে।

ভাঙ্গন ঠিক করুন

নিম্নলিখিত বিভাগগুলি আপনাকে বলে যে কীভাবে নির্দিষ্ট ধরণের ভাঙ্গন ঠিক করতে হয়।

বিল্ড ত্রুটি: CLC অমিল

বিল্ড সিস্টেম 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 সেট করুন৷ বিল্ড-টাইম কোহেরেন্স চেক এখনও সঞ্চালিত হয়, কিন্তু একটি চেক ব্যর্থতার মানে বিল্ড ব্যর্থতা নয়। পরিবর্তে, একটি চেক ব্যর্থতা বিল্ড সিস্টেমকে dex2oat কম্পাইলার ফিল্টারকে dexpreopt-এ 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 মডিউলগুলির জন্য:

  1. মডিউলের libs সম্পত্তিতে অনুপস্থিত লাইব্রেরি সন্ধান করুন। যদি এটি থাকে, Soong সাধারণত এই ধরনের বিশেষ ক্ষেত্রে ব্যতীত স্বয়ংক্রিয়ভাবে এই ধরনের লাইব্রেরি যোগ করে:

    • লাইব্রেরিটি একটি SDK লাইব্রেরি নয় (এটি java_sdk_library পরিবর্তে java_library হিসাবে সংজ্ঞায়িত করা হয়েছে)।
    • লাইব্রেরির মডিউল নাম (বিল্ড সিস্টেমে) থেকে আলাদা লাইব্রেরির নাম (মেনিফেস্টে) রয়েছে।

    এটি সাময়িকভাবে ঠিক করতে, Android.bp লাইব্রেরির সংজ্ঞায় provides_uses_lib: "<library-name>" যোগ করুন। দীর্ঘমেয়াদী সমাধানের জন্য, অন্তর্নিহিত সমস্যাটি ঠিক করুন: লাইব্রেরিটিকে একটি SDK লাইব্রেরিতে রূপান্তর করুন, বা এর মডিউলের নাম পরিবর্তন করুন৷

  2. যদি পূর্ববর্তী ধাপটি একটি রেজোলিউশন প্রদান না করে, তাহলে প্রয়োজনীয় লাইব্রেরির জন্য uses_libs: ["<library-module-name>"] যোগ করুন, অথবা Android.bp এ ঐচ্ছিক লাইব্রেরির জন্য optional_uses_libs: ["<library-module-name>"] । মডিউলের Android.bp সংজ্ঞা। এই বৈশিষ্ট্যগুলি মডিউল নামের একটি তালিকা গ্রহণ করে। তালিকায় থাকা লাইব্রেরিগুলির আপেক্ষিক ক্রমটি ম্যানিফেস্টের ক্রমটির মতোই হতে হবে৷

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> যোগ করুন; মডিউলের Android.mk সংজ্ঞাতে ঐচ্ছিক লাইব্রেরির জন্য LOCAL_OPTIONAL_USES_LIBRARIES := <library-module-name> যোগ করুন। এই বৈশিষ্ট্যগুলি মডিউল নামের একটি তালিকা গ্রহণ করে। তালিকায় লাইব্রেরির আপেক্ষিক ক্রম ম্যানিফেস্টের মতোই হতে হবে।

বিল্ড ত্রুটি: অজানা লাইব্রেরি পথ

যদি বিল্ড সিস্টেম একটি <uses-library> DEX জার (হয় একটি বিল্ড-টাইম পাথ অন-হোস্ট বা একটি ইনস্টল পাথ অন-ডিভাইস), এটি সাধারণত বিল্ড ব্যর্থ হয়. একটি পথ খুঁজে পেতে ব্যর্থতা নির্দেশ করতে পারে যে লাইব্রেরিটি কিছু অপ্রত্যাশিত উপায়ে কনফিগার করা হয়েছে। সমস্যাযুক্ত মডিউলটির জন্য 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 অমিল

প্রথম বুটে, 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 হল একটি গাছের মতো কাঠামো যা ক্লাস-লোডার শ্রেণিবিন্যাস বর্ণনা করে। বিল্ড সিস্টেমটি একটি সংকীর্ণ অর্থে CLC ব্যবহার করে (এটি শুধুমাত্র লাইব্রেরি কভার করে, APK বা কাস্টম-ক্লাস লোডার নয়): এটি লাইব্রেরির একটি ট্রি যা একটি লাইব্রেরি বা অ্যাপের সমস্ত <uses-library> নির্ভরতার ট্রানজিটিভ বন্ধের প্রতিনিধিত্ব করে। একটি CLC-এর টপলেভেল উপাদান হল সরাসরি <uses-library> নির্ভরতা যা ম্যানিফেস্টে (ক্লাসপাথ) নির্দিষ্ট করা হয়েছে। একটি CLC গাছের প্রতিটি নোড হল একটি <uses-library> নোড যার নিজস্ব <uses-library> সাব-নোড থাকতে পারে।

যেহেতু <uses-library> নির্ভরতাগুলি একটি নির্দেশিত অ্যাসাইক্লিক গ্রাফ, এবং অগত্যা একটি গাছ নয়, CLC একই লাইব্রেরির জন্য একাধিক সাবট্রি ধারণ করতে পারে। অন্য কথায়, CLC হল একটি গাছের উপর "উন্মোচিত" নির্ভরতা গ্রাফ। নকল শুধুমাত্র একটি যৌক্তিক স্তরে; প্রকৃত অন্তর্নিহিত ক্লাস লোডারগুলি নকল করা হয় না (রানটাইমে প্রতিটি লাইব্রেরির জন্য একটি একক ক্লাস লোডার উদাহরণ থাকে)।

লাইব্রেরি বা অ্যাপ দ্বারা ব্যবহৃত জাভা ক্লাসগুলি সমাধান করার সময় CLC লাইব্রেরিগুলির সন্ধানের ক্রম নির্ধারণ করে। লুকআপ অর্ডার গুরুত্বপূর্ণ কারণ লাইব্রেরিতে ডুপ্লিকেট ক্লাস থাকতে পারে এবং ক্লাসটি প্রথম ম্যাচের জন্য সমাধান করা হয়।

ডিভাইসে (রান-টাইম) CLC

PackageManager ( frameworks/base এ) ডিভাইসে একটি জাভা মডিউল লোড করার জন্য একটি CLC তৈরি করে। এটি শীর্ষ-স্তরের CLC উপাদান হিসাবে মডিউলের ম্যানিফেস্টে <uses-library> ট্যাগে তালিকাভুক্ত লাইব্রেরিগুলিকে যুক্ত করে।

প্রতিটি ব্যবহৃত লাইব্রেরির জন্য, PackageManager তার সমস্ত <uses-library> নির্ভরতা পায় (সেই লাইব্রেরির ম্যানিফেস্টে ট্যাগ হিসাবে নির্দিষ্ট) এবং প্রতিটি নির্ভরতার জন্য একটি নেস্টেড CLC যোগ করে। এই প্রক্রিয়াটি পুনরাবৃত্তভাবে চলতে থাকে যতক্ষণ না নির্মাণ করা CLC গাছের সমস্ত লিফ নোড <uses-library> নির্ভরতা ছাড়াই লাইব্রেরি হয়।

PackageManager শুধুমাত্র শেয়ার করা লাইব্রেরি সম্পর্কে সচেতন। এই ব্যবহারে ভাগ করা সংজ্ঞাটি এর স্বাভাবিক অর্থ থেকে পৃথক (যেমন ভাগ করা বনাম স্ট্যাটিক)। অ্যান্ড্রয়েডে, জাভা শেয়ার করা লাইব্রেরিগুলি হল XML কনফিগারে তালিকাভুক্ত যেগুলি ডিভাইসে ইনস্টল করা আছে ( /system/etc/permissions/platform.xml )। প্রতিটি এন্ট্রিতে একটি শেয়ার্ড লাইব্রেরির নাম, এর DEX জার ফাইলের একটি পাথ এবং নির্ভরতার একটি তালিকা রয়েছে (অন্যান্য শেয়ার্ড লাইব্রেরি যা এটি রানটাইমে ব্যবহার করে এবং এর ম্যানিফেস্টে <uses-library> ট্যাগগুলিতে নির্দিষ্ট করে)।

অন্য কথায়, তথ্যের দুটি উৎস রয়েছে যা PackageManager রানটাইমে CLC তৈরি করতে দেয়: ম্যানিফেস্টে <uses-library> ট্যাগ, এবং XML কনফিগারেশনে শেয়ার করা লাইব্রেরি নির্ভরতা।

অন-হোস্ট (বিল্ড-টাইম) সিএলসি

CLC শুধুমাত্র একটি লাইব্রেরি বা একটি অ্যাপ লোড করার সময় প্রয়োজন হয় না, এটি একটি কম্পাইল করার সময়ও প্রয়োজন। কম্পাইলেশন হয় অন-ডিভাইস (ডেক্সপট) বা বিল্ডের সময় (ডেক্সপ্রিওপ্ট) ঘটতে পারে। যেহেতু dexopt ডিভাইসে সংঘটিত হয়, এতে PackageManager (প্রকাশিত এবং ভাগ করা লাইব্রেরি নির্ভরতা) হিসাবে একই তথ্য রয়েছে। Dexpreopt, তবে, হোস্টে এবং সম্পূর্ণ ভিন্ন পরিবেশে সঞ্চালিত হয় এবং এটিকে বিল্ড সিস্টেম থেকে একই তথ্য পেতে হবে।

এইভাবে, dexpreopt দ্বারা ব্যবহৃত বিল্ড-টাইম CLC এবং PackageManager দ্বারা ব্যবহৃত রান-টাইম CLC একই জিনিস, কিন্তু দুটি ভিন্ন উপায়ে গণনা করা হয়।

বিল্ড-টাইম এবং রান-টাইম সিএলসি অবশ্যই মিলে যাবে, অন্যথায় dexpreopt দ্বারা তৈরি AOT-সংকলিত কোড প্রত্যাখ্যান করা হবে। বিল্ড-টাইম এবং রান-টাইম CLC-এর সমতা পরীক্ষা করতে, dex2oat কম্পাইলার *.odex ফাইলে (OAT ফাইল হেডারের classpath ক্ষেত্রে) বিল্ড-টাইম CLC রেকর্ড করে। সঞ্চিত CLC খুঁজে পেতে, এই কমান্ডটি ব্যবহার করুন:

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

বুট করার সময় লগক্যাটে বিল্ড-টাইম এবং রান-টাইম CLC গরমিল রিপোর্ট করা হয়েছে। এই কমান্ড দিয়ে এটি অনুসন্ধান করুন:

logcat | grep -E 'ClassLoaderContext [az ]+ mismatch'

অসামঞ্জস্য কর্মক্ষমতার জন্য খারাপ, কারণ এটি লাইব্রেরি বা অ্যাপকে হয় dexopted হতে বাধ্য করে, অথবা অপটিমাইজেশন ছাড়াই চালাতে বাধ্য করে (উদাহরণস্বরূপ, অ্যাপের কোডটি APK থেকে মেমরিতে বের করতে হতে পারে, এটি একটি অত্যন্ত ব্যয়বহুল অপারেশন)।

একটি ভাগ করা লাইব্রেরি ঐচ্ছিক বা প্রয়োজনীয় হতে পারে। dexpreopt দৃষ্টিকোণ থেকে, একটি প্রয়োজনীয় লাইব্রেরি নির্মাণের সময় উপস্থিত থাকতে হবে (এর অনুপস্থিতি একটি বিল্ড ত্রুটি)। একটি ঐচ্ছিক লাইব্রেরি নির্মাণের সময় উপস্থিত বা অনুপস্থিত হতে পারে: যদি উপস্থিত থাকে, তাহলে এটি CLC-তে যোগ করা হয়, dex2oat-এ পাস করা হয় এবং *.odex ফাইলে রেকর্ড করা হয়। যদি একটি ঐচ্ছিক লাইব্রেরি অনুপস্থিত থাকে, এটি এড়িয়ে যাওয়া হয় এবং CLC এ যোগ করা হয় না। যদি বিল্ড-টাইম এবং রান-টাইম স্ট্যাটাসের মধ্যে অমিল থাকে (একটি ক্ষেত্রে ঐচ্ছিক লাইব্রেরি উপস্থিত থাকে, কিন্তু অন্য ক্ষেত্রে নয়), তাহলে বিল্ড-টাইম এবং রান-টাইম CLC মেলে না এবং কম্পাইল করা কোড প্রত্যাখ্যান করা হয়।

উন্নত বিল্ড সিস্টেমের বিশদ বিবরণ (মেনিফেস্ট ফিক্সার)

কখনও কখনও <uses-library> ট্যাগগুলি একটি লাইব্রেরি বা অ্যাপের সোর্স ম্যানিফেস্ট থেকে অনুপস্থিত থাকে। এটি ঘটতে পারে, উদাহরণস্বরূপ, যদি লাইব্রেরি বা অ্যাপের একটি ট্রানজিটিভ নির্ভরতা অন্য একটি <uses-library> ট্যাগ ব্যবহার করা শুরু করে এবং এটি অন্তর্ভুক্ত করার জন্য লাইব্রেরি বা অ্যাপের ম্যানিফেস্ট আপডেট করা না হয়।

Soong একটি প্রদত্ত লাইব্রেরি বা অ্যাপের জন্য কিছু অনুপস্থিত <uses-library> ট্যাগ স্বয়ংক্রিয়ভাবে গণনা করতে পারে, যেমন SDK লাইব্রেরি লাইব্রেরি বা অ্যাপের ট্রানজিটিভ নির্ভরতা বন্ধে। বন্ধ করা প্রয়োজন কারণ লাইব্রেরি (বা অ্যাপ) একটি স্ট্যাটিক লাইব্রেরির উপর নির্ভর করতে পারে যা একটি SDK লাইব্রেরির উপর নির্ভর করে এবং সম্ভবত আবার অন্য লাইব্রেরির মাধ্যমে ট্রানজিটিভভাবে নির্ভর করতে পারে।

সমস্ত <uses-library> ট্যাগ এইভাবে গণনা করা যায় না, কিন্তু যখন সম্ভব, Soong কে স্বয়ংক্রিয়ভাবে ম্যানিফেস্ট এন্ট্রি যোগ করতে দেওয়া বাঞ্ছনীয়; এটি কম ত্রুটি-প্রবণ এবং রক্ষণাবেক্ষণকে সহজ করে। উদাহরণস্বরূপ, যখন অনেক অ্যাপ একটি স্ট্যাটিক লাইব্রেরি ব্যবহার করে যা একটি নতুন <uses-library> নির্ভরতা যোগ করে, তখন সমস্ত অ্যাপ আপডেট করতে হবে, যা বজায় রাখা কঠিন।

,

Android 12-এ <uses-library> নির্ভরতা আছে এমন Java মডিউলগুলির জন্য DEX ফাইলের (dexpreopt) AOT সংকলনে সিস্টেম পরিবর্তনগুলি তৈরি করা হয়েছে। কিছু ক্ষেত্রে এই বিল্ড সিস্টেম পরিবর্তন বিল্ড ভেঙ্গে দিতে পারে। ভাঙ্গনের জন্য প্রস্তুত করতে এই পৃষ্ঠাটি ব্যবহার করুন এবং সেগুলিকে ঠিক করতে এবং প্রশমিত করতে এই পৃষ্ঠার রেসিপিগুলি অনুসরণ করুন৷

ডেক্সপ্রিওপ্ট হল জাভা লাইব্রেরি এবং অ্যাপের আগাম সংকলনের প্রক্রিয়া। ডেক্সপ্রিওপ্ট বিল্ড টাইমে অন-হোস্ট হয় ( ডেক্সপট এর বিপরীতে, যা ডিভাইসে ঘটে)। একটি জাভা মডিউল (একটি লাইব্রেরি বা একটি অ্যাপ) দ্বারা ব্যবহৃত শেয়ার্ড লাইব্রেরি নির্ভরতার কাঠামোটি এর ক্লাস লোডার প্রসঙ্গ (CLC) নামে পরিচিত। ডেক্সপ্রিওপ্টের সঠিকতার গ্যারান্টি দিতে, বিল্ড-টাইম এবং রান-টাইম সিএলসি অবশ্যই মিলে যাবে। বিল্ড-টাইম CLC হল যা dex2oat কম্পাইলার dexpreopt সময়ে ব্যবহার করে (এটি ODEX ফাইলগুলিতে রেকর্ড করা হয়), এবং রান-টাইম CLC হল সেই প্রেক্ষাপট যেখানে প্রি-কম্পাইল করা কোড ডিভাইসে লোড করা হয়।

এই বিল্ড-টাইম এবং রান-টাইম সিএলসি অবশ্যই সঠিকতা এবং কর্মক্ষমতা উভয়ের কারণেই মিলে যাবে। সঠিকতার জন্য, ডুপ্লিকেট ক্লাস পরিচালনা করা প্রয়োজন। রানটাইমে শেয়ার্ড লাইব্রেরি নির্ভরতাগুলি সংকলনের জন্য ব্যবহৃত লাইব্রেরিগুলির থেকে আলাদা হলে, কিছু ক্লাস আলাদাভাবে সমাধান করা যেতে পারে, যার ফলে সূক্ষ্ম রানটাইম বাগগুলি হতে পারে। ডুপ্লিকেট ক্লাসের জন্য রানটাইম চেক দ্বারা কর্মক্ষমতাও প্রভাবিত হয়।

প্রভাবিত ব্যবহারের ক্ষেত্রে

প্রথম বুট হল প্রধান ব্যবহারের ক্ষেত্রে যা এই পরিবর্তনগুলির দ্বারা প্রভাবিত হয়: যদি ART বিল্ড-টাইম এবং রান-টাইম CLC-এর মধ্যে একটি অমিল শনাক্ত করে, তবে এটি dexpreopt আর্টিফ্যাক্টগুলি প্রত্যাখ্যান করে এবং পরিবর্তে dexopt চালায়। পরবর্তী বুটগুলির জন্য এটি ঠিক কারণ অ্যাপগুলিকে ব্যাকগ্রাউন্ডে ডিক্সপ্ট করা যায় এবং ডিস্কে সংরক্ষণ করা যায়।

অ্যান্ড্রয়েডের প্রভাবিত এলাকা

এটি অন্যান্য জাভা লাইব্রেরিতে রানটাইম নির্ভরতা আছে এমন সমস্ত জাভা অ্যাপ এবং লাইব্রেরিকে প্রভাবিত করে। অ্যান্ড্রয়েডের হাজার হাজার অ্যাপ রয়েছে এবং সেগুলির শত শত শেয়ার করা লাইব্রেরি ব্যবহার করে। অংশীদাররাও প্রভাবিত হয়, কারণ তাদের নিজস্ব লাইব্রেরি এবং অ্যাপ রয়েছে।

বিরতি পরিবর্তন

dexpreopt বিল্ড নিয়ম তৈরি করার আগে বিল্ড সিস্টেমকে <uses-library> নির্ভরতা জানতে হবে। যাইহোক, এটি সরাসরি ম্যানিফেস্ট অ্যাক্সেস করতে পারে না এবং এটিতে <uses-library> ট্যাগগুলি পড়তে পারে না, কারণ বিল্ড সিস্টেমটি যখন বিল্ড নিয়ম তৈরি করে (কর্মক্ষমতার কারণে) নির্বিচারে ফাইলগুলি পড়ার অনুমতি দেয় না। তদুপরি, ম্যানিফেস্টটি একটি APK বা পূর্বনির্মাণের ভিতরে প্যাকেজ করা হতে পারে। অতএব, <uses-library> তথ্য অবশ্যই বিল্ড ফাইলগুলিতে উপস্থিত থাকতে হবে ( Android.bp বা Android.mk )।

পূর্বে ART একটি সমাধান ব্যবহার করত যা ভাগ করা লাইব্রেরি নির্ভরতাকে উপেক্ষা করত (যা &-classpath নামে পরিচিত)। এটি অনিরাপদ ছিল এবং সূক্ষ্ম বাগ সৃষ্টি করেছিল, তাই অ্যান্ড্রয়েড 12 এ সমাধানটি সরিয়ে দেওয়া হয়েছিল।

ফলস্বরূপ, জাভা মডিউল যেগুলি তাদের বিল্ড ফাইলগুলিতে সঠিক <uses-library> তথ্য প্রদান করে না সেগুলি বিল্ড ব্রেকেজ (একটি বিল্ড-টাইম CLC অমিলের কারণে) বা প্রথম-বুট টাইম রিগ্রেশন (বুট-টাইম CLC দ্বারা সৃষ্ট) হতে পারে dexopt দ্বারা অনুসৃত অমিল)।

অভিবাসন পথ

একটি ভাঙা বিল্ড ঠিক করতে এই পদক্ষেপগুলি অনুসরণ করুন:

  1. বিশ্বব্যাপী সেট করে একটি নির্দিষ্ট পণ্যের জন্য বিল্ড-টাইম চেক অক্ষম করুন

    PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true

    পণ্যের মেকফাইলে। এটি বিল্ড ত্রুটিগুলি সংশোধন করে (বিশেষ ক্ষেত্রে ছাড়া, ফিক্সিং ব্রেকেজ বিভাগে তালিকাভুক্ত)। যাইহোক, এটি একটি অস্থায়ী সমাধান, এবং এটি dexopt দ্বারা অনুসরণ করে বুট-টাইম CLC অমিল হতে পারে।

  2. আপনার বিল্ড-টাইম চেক বিশ্বব্যাপী অক্ষম করার আগে ব্যর্থ হওয়া মডিউলগুলিকে তাদের বিল্ড ফাইলগুলিতে প্রয়োজনীয় <uses-library> তথ্য যোগ করে ঠিক করুন (বিশদ বিবরণের জন্য বিচ্ছেদের সংশোধন দেখুন)। বেশিরভাগ মডিউলের জন্য এর জন্য Android.bp বা Android.mk এ কয়েকটি লাইন যোগ করা প্রয়োজন।

  3. প্রতি-মডিউল ভিত্তিতে, সমস্যাযুক্ত ক্ষেত্রে বিল্ড-টাইম চেক এবং ডেক্সপ্রিওপ্ট অক্ষম করুন। dexpreopt অক্ষম করুন যাতে আপনি বুট করার সময় প্রত্যাখ্যাত আর্টিফ্যাক্টগুলিতে বিল্ড সময় এবং স্টোরেজ নষ্ট করবেন না।

  4. ধাপ 1 এ সেট করা PRODUCT_BROKEN_VERIFY_USES_LIBRARIES আনসেট করে বিশ্বব্যাপী বিল্ড-টাইম চেক পুনরায়-সক্ষম করুন; এই পরিবর্তনের পরে বিল্ডটি ব্যর্থ হওয়া উচিত নয় (পদক্ষেপ 2 এবং 3 এর কারণে)।

  5. আপনি ধাপ 3-এ অক্ষম করা মডিউলগুলিকে এক সময়ে ঠিক করুন, তারপরে dexpreopt পুনরায় সক্রিয় করুন এবং <uses-library> চেক করুন। প্রয়োজনে বাগ ফাইল করুন।

Android 12-এ বিল্ড-টাইম <uses-library> চেক প্রয়োগ করা হয়েছে।

ভাঙ্গন ঠিক করুন

নিম্নলিখিত বিভাগগুলি আপনাকে বলে যে কীভাবে নির্দিষ্ট ধরণের ভাঙ্গন ঠিক করতে হয়।

বিল্ড ত্রুটি: CLC অমিল

বিল্ড সিস্টেম 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 সেট করুন৷ বিল্ড-টাইম কোহেরেন্স চেক এখনও সঞ্চালিত হয়, কিন্তু একটি চেক ব্যর্থতার মানে বিল্ড ব্যর্থতা নয়। পরিবর্তে, একটি চেক ব্যর্থতা বিল্ড সিস্টেমকে dex2oat কম্পাইলার ফিল্টারকে dexpreopt-এ 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 মডিউলগুলির জন্য:

  1. মডিউলের libs সম্পত্তিতে অনুপস্থিত লাইব্রেরি সন্ধান করুন। যদি এটি থাকে, Soong সাধারণত এই ধরনের বিশেষ ক্ষেত্রে ব্যতীত স্বয়ংক্রিয়ভাবে এই ধরনের লাইব্রেরি যোগ করে:

    • লাইব্রেরিটি একটি SDK লাইব্রেরি নয় (এটি java_sdk_library পরিবর্তে java_library হিসাবে সংজ্ঞায়িত করা হয়েছে)।
    • লাইব্রেরির মডিউল নাম (বিল্ড সিস্টেমে) থেকে আলাদা লাইব্রেরির নাম (মেনিফেস্টে) রয়েছে।

    এটি সাময়িকভাবে ঠিক করতে, Android.bp লাইব্রেরির সংজ্ঞায় provides_uses_lib: "<library-name>" যোগ করুন। দীর্ঘমেয়াদী সমাধানের জন্য, অন্তর্নিহিত সমস্যাটি ঠিক করুন: লাইব্রেরিটিকে একটি SDK লাইব্রেরিতে রূপান্তর করুন, বা এর মডিউলের নাম পরিবর্তন করুন৷

  2. যদি পূর্ববর্তী ধাপটি একটি রেজোলিউশন প্রদান না করে, তাহলে প্রয়োজনীয় লাইব্রেরির জন্য uses_libs: ["<library-module-name>"] যোগ করুন, অথবা Android.bp এ ঐচ্ছিক লাইব্রেরির জন্য optional_uses_libs: ["<library-module-name>"] । মডিউলের Android.bp সংজ্ঞা। এই বৈশিষ্ট্যগুলি মডিউল নামের একটি তালিকা গ্রহণ করে। তালিকায় থাকা লাইব্রেরিগুলির আপেক্ষিক ক্রমটি ম্যানিফেস্টের ক্রমটির মতোই হতে হবে৷

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> যোগ করুন; মডিউলের Android.mk সংজ্ঞাতে ঐচ্ছিক লাইব্রেরির জন্য LOCAL_OPTIONAL_USES_LIBRARIES := <library-module-name> যোগ করুন। এই বৈশিষ্ট্যগুলি মডিউল নামের একটি তালিকা গ্রহণ করে। তালিকায় লাইব্রেরির আপেক্ষিক ক্রম ম্যানিফেস্টের মতোই হতে হবে।

বিল্ড ত্রুটি: অজানা লাইব্রেরি পথ

যদি বিল্ড সিস্টেম একটি <uses-library> DEX জার (হয় একটি বিল্ড-টাইম পাথ অন-হোস্ট বা একটি ইনস্টল পাথ অন-ডিভাইস), এটি সাধারণত বিল্ড ব্যর্থ হয়. একটি পথ খুঁজে পেতে ব্যর্থতা নির্দেশ করতে পারে যে লাইব্রেরিটি কিছু অপ্রত্যাশিত উপায়ে কনফিগার করা হয়েছে। সমস্যাযুক্ত মডিউলটির জন্য 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 অমিল

প্রথম বুটে, 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 হল একটি গাছের মতো কাঠামো যা ক্লাস-লোডার শ্রেণিবিন্যাস বর্ণনা করে। বিল্ড সিস্টেমটি একটি সংকীর্ণ অর্থে CLC ব্যবহার করে (এটি শুধুমাত্র লাইব্রেরি কভার করে, APK বা কাস্টম-ক্লাস লোডার নয়): এটি লাইব্রেরির একটি ট্রি যা একটি লাইব্রেরি বা অ্যাপের সমস্ত <uses-library> নির্ভরতার ট্রানজিটিভ বন্ধের প্রতিনিধিত্ব করে। একটি CLC-এর টপলেভেল উপাদান হল সরাসরি <uses-library> নির্ভরতা যা ম্যানিফেস্টে (ক্লাসপাথ) নির্দিষ্ট করা হয়েছে। একটি CLC গাছের প্রতিটি নোড হল একটি <uses-library> নোড যার নিজস্ব <uses-library> সাব-নোড থাকতে পারে।

যেহেতু <uses-library> নির্ভরতাগুলি একটি নির্দেশিত অ্যাসাইক্লিক গ্রাফ, এবং অগত্যা একটি গাছ নয়, CLC একই লাইব্রেরির জন্য একাধিক সাবট্রি ধারণ করতে পারে। অন্য কথায়, CLC হল একটি গাছের উপর "উন্মোচিত" নির্ভরতা গ্রাফ। নকল শুধুমাত্র একটি যৌক্তিক স্তরে; প্রকৃত অন্তর্নিহিত ক্লাস লোডারগুলি নকল করা হয় না (রানটাইমে প্রতিটি লাইব্রেরির জন্য একটি একক ক্লাস লোডার উদাহরণ থাকে)।

লাইব্রেরি বা অ্যাপ দ্বারা ব্যবহৃত জাভা ক্লাসগুলি সমাধান করার সময় CLC লাইব্রেরিগুলির সন্ধানের ক্রম নির্ধারণ করে। লুকআপ অর্ডার গুরুত্বপূর্ণ কারণ লাইব্রেরিতে ডুপ্লিকেট ক্লাস থাকতে পারে এবং ক্লাসটি প্রথম ম্যাচের জন্য সমাধান করা হয়।

ডিভাইসে (রান-টাইম) CLC

PackageManager ( frameworks/base এ) ডিভাইসে একটি জাভা মডিউল লোড করার জন্য একটি CLC তৈরি করে। এটি শীর্ষ-স্তরের CLC উপাদান হিসাবে মডিউলের ম্যানিফেস্টে <uses-library> ট্যাগে তালিকাভুক্ত লাইব্রেরিগুলিকে যুক্ত করে।

প্রতিটি ব্যবহৃত লাইব্রেরির জন্য, PackageManager তার সমস্ত <uses-library> নির্ভরতা পায় (সেই লাইব্রেরির ম্যানিফেস্টে ট্যাগ হিসাবে নির্দিষ্ট) এবং প্রতিটি নির্ভরতার জন্য একটি নেস্টেড CLC যোগ করে। এই প্রক্রিয়াটি পুনরাবৃত্তভাবে চলতে থাকে যতক্ষণ না নির্মাণ করা CLC গাছের সমস্ত লিফ নোড <uses-library> নির্ভরতা ছাড়াই লাইব্রেরি হয়।

PackageManager শুধুমাত্র শেয়ার করা লাইব্রেরি সম্পর্কে সচেতন। এই ব্যবহারে ভাগ করা সংজ্ঞাটি এর স্বাভাবিক অর্থ থেকে পৃথক (যেমন ভাগ করা বনাম স্ট্যাটিক)। অ্যান্ড্রয়েডে, জাভা শেয়ার করা লাইব্রেরিগুলি হল XML কনফিগারে তালিকাভুক্ত যেগুলি ডিভাইসে ইনস্টল করা আছে ( /system/etc/permissions/platform.xml )। প্রতিটি এন্ট্রিতে একটি শেয়ার্ড লাইব্রেরির নাম, এর DEX জার ফাইলের একটি পাথ এবং নির্ভরতার একটি তালিকা রয়েছে (অন্যান্য শেয়ার্ড লাইব্রেরি যা এটি রানটাইমে ব্যবহার করে এবং এর ম্যানিফেস্টে <uses-library> ট্যাগগুলিতে নির্দিষ্ট করে)।

অন্য কথায়, তথ্যের দুটি উৎস রয়েছে যা PackageManager রানটাইমে CLC তৈরি করতে দেয়: ম্যানিফেস্টে <uses-library> ট্যাগ, এবং XML কনফিগারেশনে শেয়ার করা লাইব্রেরি নির্ভরতা।

অন-হোস্ট (বিল্ড-টাইম) সিএলসি

CLC শুধুমাত্র একটি লাইব্রেরি বা একটি অ্যাপ লোড করার সময় প্রয়োজন হয় না, এটি একটি কম্পাইল করার সময়ও প্রয়োজন। কম্পাইলেশন হয় অন-ডিভাইস (ডেক্সপট) বা বিল্ডের সময় (ডেক্সপ্রিওপ্ট) ঘটতে পারে। যেহেতু dexopt ডিভাইসে সংঘটিত হয়, এতে PackageManager (প্রকাশিত এবং ভাগ করা লাইব্রেরি নির্ভরতা) হিসাবে একই তথ্য রয়েছে। Dexpreopt, তবে, হোস্টে এবং সম্পূর্ণ ভিন্ন পরিবেশে সঞ্চালিত হয় এবং এটিকে বিল্ড সিস্টেম থেকে একই তথ্য পেতে হবে।

এইভাবে, dexpreopt দ্বারা ব্যবহৃত বিল্ড-টাইম CLC এবং PackageManager দ্বারা ব্যবহৃত রান-টাইম CLC একই জিনিস, কিন্তু দুটি ভিন্ন উপায়ে গণনা করা হয়।

বিল্ড-টাইম এবং রান-টাইম সিএলসি অবশ্যই মিলে যাবে, অন্যথায় dexpreopt দ্বারা তৈরি AOT-সংকলিত কোড প্রত্যাখ্যান করা হবে। বিল্ড-টাইম এবং রান-টাইম CLC-এর সমতা পরীক্ষা করতে, dex2oat কম্পাইলার *.odex ফাইলে (OAT ফাইল হেডারের classpath ক্ষেত্রে) বিল্ড-টাইম CLC রেকর্ড করে। সঞ্চিত CLC খুঁজে পেতে, এই কমান্ডটি ব্যবহার করুন:

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

বুট করার সময় লগক্যাটে বিল্ড-টাইম এবং রান-টাইম CLC গরমিল রিপোর্ট করা হয়েছে। এই কমান্ড দিয়ে এটি অনুসন্ধান করুন:

logcat | grep -E 'ClassLoaderContext [az ]+ mismatch'

অসামঞ্জস্য কর্মক্ষমতার জন্য খারাপ, কারণ এটি লাইব্রেরি বা অ্যাপকে হয় dexopted হতে বাধ্য করে, অথবা অপটিমাইজেশন ছাড়াই চালাতে বাধ্য করে (উদাহরণস্বরূপ, অ্যাপের কোডটি APK থেকে মেমরিতে বের করতে হতে পারে, এটি একটি অত্যন্ত ব্যয়বহুল অপারেশন)।

একটি ভাগ করা লাইব্রেরি ঐচ্ছিক বা প্রয়োজনীয় হতে পারে। dexpreopt দৃষ্টিকোণ থেকে, একটি প্রয়োজনীয় লাইব্রেরি নির্মাণের সময় উপস্থিত থাকতে হবে (এর অনুপস্থিতি একটি বিল্ড ত্রুটি)। একটি ঐচ্ছিক লাইব্রেরি নির্মাণের সময় উপস্থিত বা অনুপস্থিত হতে পারে: যদি উপস্থিত থাকে, তাহলে এটি CLC-তে যোগ করা হয়, dex2oat-এ পাস করা হয় এবং *.odex ফাইলে রেকর্ড করা হয়। যদি একটি ঐচ্ছিক লাইব্রেরি অনুপস্থিত থাকে, এটি এড়িয়ে যাওয়া হয় এবং CLC এ যোগ করা হয় না। যদি বিল্ড-টাইম এবং রান-টাইম স্ট্যাটাসের মধ্যে অমিল থাকে (একটি ক্ষেত্রে ঐচ্ছিক লাইব্রেরি উপস্থিত থাকে, কিন্তু অন্য ক্ষেত্রে নয়), তাহলে বিল্ড-টাইম এবং রান-টাইম CLC মেলে না এবং কম্পাইল করা কোড প্রত্যাখ্যান করা হয়।

উন্নত বিল্ড সিস্টেমের বিশদ বিবরণ (মেনিফেস্ট ফিক্সার)

কখনও কখনও <uses-library> ট্যাগগুলি একটি লাইব্রেরি বা অ্যাপের সোর্স ম্যানিফেস্ট থেকে অনুপস্থিত থাকে। এটি ঘটতে পারে, উদাহরণস্বরূপ, যদি লাইব্রেরি বা অ্যাপের একটি ট্রানজিটিভ নির্ভরতা অন্য একটি <uses-library> ট্যাগ ব্যবহার করা শুরু করে এবং এটি অন্তর্ভুক্ত করার জন্য লাইব্রেরি বা অ্যাপের ম্যানিফেস্ট আপডেট করা না হয়।

Soong একটি প্রদত্ত লাইব্রেরি বা অ্যাপের জন্য কিছু অনুপস্থিত <uses-library> ট্যাগ স্বয়ংক্রিয়ভাবে গণনা করতে পারে, যেমন SDK লাইব্রেরি লাইব্রেরি বা অ্যাপের ট্রানজিটিভ নির্ভরতা বন্ধে। বন্ধ করা প্রয়োজন কারণ লাইব্রেরি (বা অ্যাপ) একটি স্ট্যাটিক লাইব্রেরির উপর নির্ভর করতে পারে যা একটি SDK লাইব্রেরির উপর নির্ভর করে এবং সম্ভবত আবার অন্য লাইব্রেরির মাধ্যমে ট্রানজিটিভভাবে নির্ভর করতে পারে।

সমস্ত <uses-library> ট্যাগ এইভাবে গণনা করা যায় না, কিন্তু যখন সম্ভব, Soong কে স্বয়ংক্রিয়ভাবে ম্যানিফেস্ট এন্ট্রি যোগ করতে দেওয়া বাঞ্ছনীয়; এটি কম ত্রুটি-প্রবণ এবং রক্ষণাবেক্ষণকে সহজ করে। উদাহরণস্বরূপ, যখন অনেক অ্যাপ একটি স্ট্যাটিক লাইব্রেরি ব্যবহার করে যা একটি নতুন <uses-library> নির্ভরতা যোগ করে, তখন সমস্ত অ্যাপ আপডেট করতে হবে, যা বজায় রাখা কঠিন।

,

Android 12-এ <uses-library> নির্ভরতা আছে এমন Java মডিউলগুলির জন্য DEX ফাইলের (dexpreopt) AOT সংকলনে সিস্টেম পরিবর্তনগুলি তৈরি করা হয়েছে। কিছু ক্ষেত্রে এই বিল্ড সিস্টেম পরিবর্তন বিল্ড ভেঙ্গে দিতে পারে। ভাঙ্গনের জন্য প্রস্তুত করতে এই পৃষ্ঠাটি ব্যবহার করুন এবং সেগুলিকে ঠিক করতে এবং প্রশমিত করতে এই পৃষ্ঠার রেসিপিগুলি অনুসরণ করুন৷

ডেক্সপ্রিওপ্ট হল জাভা লাইব্রেরি এবং অ্যাপের আগাম সংকলনের প্রক্রিয়া। ডেক্সপ্রিওপ্ট বিল্ড টাইমে অন-হোস্ট হয় ( ডেক্সপট এর বিপরীতে, যা ডিভাইসে ঘটে)। একটি জাভা মডিউল (একটি লাইব্রেরি বা একটি অ্যাপ) দ্বারা ব্যবহৃত শেয়ার্ড লাইব্রেরি নির্ভরতার কাঠামোটি এর ক্লাস লোডার প্রসঙ্গ (CLC) নামে পরিচিত। ডেক্সপ্রিওপ্টের সঠিকতার গ্যারান্টি দিতে, বিল্ড-টাইম এবং রান-টাইম সিএলসি অবশ্যই মিলে যাবে। বিল্ড-টাইম CLC হল যা dex2oat কম্পাইলার dexpreopt সময়ে ব্যবহার করে (এটি ODEX ফাইলগুলিতে রেকর্ড করা হয়), এবং রান-টাইম CLC হল সেই প্রেক্ষাপট যেখানে প্রি-কম্পাইল করা কোড ডিভাইসে লোড করা হয়।

এই বিল্ড-টাইম এবং রান-টাইম সিএলসি অবশ্যই সঠিকতা এবং কর্মক্ষমতা উভয়ের কারণেই মিলে যাবে। সঠিকতার জন্য, ডুপ্লিকেট ক্লাস পরিচালনা করা প্রয়োজন। রানটাইমে শেয়ার্ড লাইব্রেরি নির্ভরতাগুলি সংকলনের জন্য ব্যবহৃত লাইব্রেরিগুলির থেকে আলাদা হলে, কিছু ক্লাস আলাদাভাবে সমাধান করা যেতে পারে, যার ফলে সূক্ষ্ম রানটাইম বাগগুলি হতে পারে। কর্মক্ষমতাও নকল শ্রেণির জন্য রানটাইম চেক দ্বারা প্রভাবিত হয়।

প্রভাবিত ব্যবহারের ক্ষেত্রে

প্রথম বুটটি হ'ল প্রধান ব্যবহারের কেস যা এই পরিবর্তনগুলি দ্বারা প্রভাবিত হয়: যদি শিল্পটি বিল্ড-টাইম এবং রান-টাইম সিএলসিগুলির মধ্যে একটি অমিল সনাক্ত করে তবে এটি ডেক্সপ্রেপ্ট আর্টিফ্যাক্টগুলি প্রত্যাখ্যান করে এবং পরিবর্তে ডেক্সোপ্ট চালায়। পরবর্তী বুটগুলির জন্য এটি ঠিক আছে কারণ অ্যাপ্লিকেশনগুলি পটভূমিতে ডেক্সোপ্ট করা যায় এবং ডিস্কে সংরক্ষণ করা যায়।

অ্যান্ড্রয়েডের ক্ষতিগ্রস্থ অঞ্চলগুলি

এটি অন্যান্য জাভা লাইব্রেরিতে রানটাইম নির্ভরতা রয়েছে এমন সমস্ত জাভা অ্যাপ্লিকেশন এবং গ্রন্থাগারগুলিকে প্রভাবিত করে। অ্যান্ড্রয়েডে হাজার হাজার অ্যাপ্লিকেশন রয়েছে এবং এই শত শত ভাগ করে নেওয়া লাইব্রেরি ব্যবহার করে। অংশীদাররাও প্রভাবিত হয়, কারণ তাদের নিজস্ব গ্রন্থাগার এবং অ্যাপ্লিকেশন রয়েছে।

পরিবর্তন বিরতি

বিল্ড সিস্টেমটি ডেক্সপ্রিপ্ট বিল্ড বিধি তৈরি করার আগে <uses-library> নির্ভরতাগুলি জানতে হবে। যাইহোক, এটি সরাসরি ম্যানিফেস্টটি অ্যাক্সেস করতে পারে না এবং এতে <uses-library> ট্যাগগুলি পড়তে পারে না, কারণ বিল্ড সিস্টেমটি যখন বিল্ড বিধি তৈরি করে (পারফরম্যান্সের কারণে) যখন স্বেচ্ছাসেবী ফাইলগুলি পড়ার অনুমতি দেয় না। তদুপরি, ম্যানিফেস্টটি কোনও APK বা প্রাক -বিল্ডের ভিতরে প্যাকেজ করা যেতে পারে। অতএব, <uses-library> তথ্য অবশ্যই বিল্ড ফাইলগুলিতে উপস্থিত থাকতে হবে ( Android.bp বা Android.mk )।

পূর্বে আর্ট এমন একটি কার্যকারিতা ব্যবহার করেছিল যা ভাগ করা লাইব্রেরির নির্ভরতাগুলিকে উপেক্ষা করে ( &-classpath হিসাবে পরিচিত)। এটি অনিরাপদ ছিল এবং সূক্ষ্ম বাগগুলি তৈরি করেছিল, তাই অ্যান্ড্রয়েড 12 এ ওয়ার্কআরাউন্ডটি সরানো হয়েছিল।

ফলস্বরূপ, জাভা মডিউলগুলি যা তাদের বিল্ড ফাইলগুলিতে সঠিক <uses-library> তথ্য সরবরাহ করে না সেগুলি বিল্ড ভাঙ্গার কারণ হতে পারে (একটি বিল্ড-টাইম সিএলসি মিলের কারণে সৃষ্ট) বা প্রথম-বুট টাইম রিগ্রেশনস (বুট-টাইম সিএলসি দ্বারা সৃষ্ট ডেক্সোপ্ট অনুসরণ করে মেলে না)।

অভিবাসন পথ

একটি ভাঙা বিল্ড ঠিক করতে এই পদক্ষেপগুলি অনুসরণ করুন:

  1. সেট করে বিশ্বব্যাপী কোনও নির্দিষ্ট পণ্যের জন্য বিল্ড-টাইম চেক অক্ষম করুন

    PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true

    পণ্য মেকফাইলে। এই ফিক্সগুলি ত্রুটিগুলি তৈরি করে (বিশেষ কেস ব্যতীত, ফিক্সিং ব্রেকেজ বিভাগে তালিকাভুক্ত)। যাইহোক, এটি একটি অস্থায়ী কাজ, এবং এটি বুট-টাইম সিএলসি মিলের পরে ডেক্সোপ্ট অনুসরণ করতে পারে।

  2. আপনি বিশ্বব্যাপী তাদের বিল্ড ফাইলগুলিতে প্রয়োজনীয় <uses-library> তথ্য যুক্ত করে বিল্ড-টাইম চেকটি অক্ষম করার আগে ব্যর্থ হওয়া মডিউলগুলি ঠিক করুন (বিশদগুলির জন্য ফিক্সিং ব্রেকজগুলি দেখুন)। বেশিরভাগ মডিউলগুলির জন্য এটির জন্য Android.bp , বা Android.mk -তে কয়েকটি লাইন যুক্ত করা দরকার।

  3. প্রতি-মডিউল ভিত্তিতে সমস্যাযুক্ত কেসগুলির জন্য বিল্ড-টাইম চেক এবং ডেক্সপ্রিপ্ট অক্ষম করুন। ডেক্সপ্রিওপ্টটি অক্ষম করুন যাতে আপনি বুটে প্রত্যাখ্যান করা শিল্পগুলিতে সময় এবং সঞ্চয়স্থানের জন্য সময় এবং স্টোরেজ নষ্ট করবেন না।

  4. বিশ্বব্যাপী অনেসেটিং PRODUCT_BROKEN_VERIFY_USES_LIBRARIES দ্বারা বিল্ড-টাইম চেকটি পুনরায় সক্ষম করুন যা ধাপ 1 এ সেট করা হয়েছিল; এই পরিবর্তনের পরে বিল্ডটি ব্যর্থ হওয়া উচিত নয় (পদক্ষেপ 2 এবং 3 এর কারণে)।

  5. আপনি একবারে ধাপে 3 এ অক্ষম করেছেন এমন মডিউলগুলি ঠিক করুন, তারপরে ডেক্সপ্রিপ্ট এবং <uses-library> লাইব্রেরি> চেক পুনরায় সক্ষম করুন। প্রয়োজনে ফাইলগুলি ফাইল করুন।

বিল্ড-টাইম <uses-library> চেকগুলি অ্যান্ড্রয়েড 12 এ প্রয়োগ করা হয়।

ভাঙ্গন ঠিক করুন

নিম্নলিখিত বিভাগগুলি আপনাকে কীভাবে নির্দিষ্ট ধরণের ভাঙ্গন ঠিক করতে হয় তা জানায়।

বিল্ড ত্রুটি: সিএলসি মিল নেই

বিল্ড সিস্টেমটি Android.bp বা Android.mk ফাইল এবং ম্যানিফেস্টের তথ্যগুলির মধ্যে একটি বিল্ড-টাইম সংহতি চেক করে। বিল্ড সিস্টেমটি ম্যানিফেস্টটি পড়তে পারে না, তবে এটি ম্যানিফেস্টটি পড়ার জন্য বিল্ড বিধি তৈরি করতে পারে (প্রয়োজনে এটি একটি এপিকে থেকে বের করা), এবং <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 । বিল্ড-টাইম সমন্বয় চেকটি এখনও সম্পাদিত হয়, তবে একটি চেক ব্যর্থতার অর্থ কোনও বিল্ড ব্যর্থতা নয়। পরিবর্তে, একটি চেক ব্যর্থতা ডেক্সপ্রিওপ্টে verify করতে বিল্ড সিস্টেমটিকে ডেক্স 2 ওট সংকলক ফিল্টারকে ডাউনগ্রেড করে তোলে, যা এই মডিউলটির জন্য সম্পূর্ণরূপে এওটি-সংকলনকে অক্ষম করে।
  • একটি দ্রুত, গ্লোবাল কমান্ড-লাইন ফিক্সের জন্য, পরিবেশটি ভেরিয়েবল RELAX_USES_LIBRARY_CHECK=true ব্যবহার করুন। এটি PRODUCT_BROKEN_VERIFY_USES_LIBRARIES মতো একই প্রভাব ফেলে তবে কমান্ড-লাইনে ব্যবহারের উদ্দেশ্যে। পরিবেশ ভেরিয়েবল পণ্যের পরিবর্তনশীলকে ওভাররাইড করে।
  • মূল কারণটি ত্রুটিটি সমাধান করার সমাধানের জন্য, বিল্ড সিস্টেমটিকে ম্যানিফেস্টে <uses-library> ট্যাগগুলি সম্পর্কে সচেতন করুন। ত্রুটি বার্তার একটি পরিদর্শন দেখায় যে কোন গ্রন্থাগারগুলি সমস্যার কারণ হয় (যেমন AndroidManifest.xml বা কোনও এপিকে-র ভিতরে ম্যানিফেস্টের পরিদর্শন করা হয় যা ` aapt dump badging $APK | grep uses-library দিয়ে পরীক্ষা করা যায়)।

Android.bp মডিউলগুলির জন্য:

  1. মডিউলটির libs সম্পত্তিতে অনুপস্থিত লাইব্রেরির সন্ধান করুন। যদি এটি সেখানে থাকে তবে এই বিশেষ ক্ষেত্রে বাদে সুং সাধারণত এই জাতীয় গ্রন্থাগারগুলি স্বয়ংক্রিয়ভাবে যুক্ত করে:

    • গ্রন্থাগারটি কোনও এসডিকে লাইব্রেরি নয় (এটি java_sdk_library চেয়ে java_library হিসাবে সংজ্ঞায়িত)।
    • লাইব্রেরির মডিউল নাম (বিল্ড সিস্টেমে) থেকে একটি আলাদা লাইব্রেরির নাম (ম্যানিফেস্টে) রয়েছে।

    অস্থায়ীভাবে এটি ঠিক করতে, Android.bp লাইব্রেরি সংজ্ঞাতে provides_uses_lib: "<library-name>" দীর্ঘমেয়াদী সমাধানের জন্য, অন্তর্নিহিত সমস্যাটি ঠিক করুন: লাইব্রেরিটিকে একটি এসডিকে লাইব্রেরিতে রূপান্তর করুন বা এর মডিউলটির নাম পরিবর্তন করুন।

  2. যদি পূর্ববর্তী পদক্ষেপটি কোনও রেজোলিউশন সরবরাহ না করে তবে প্রয়োজনীয় লাইব্রেরিগুলির জন্য uses_libs: ["<library-module-name>"] , বা optional_uses_libs: ["<library-module-name>"] Android.bp মডিউলটির Android.bp সংজ্ঞা। এই বৈশিষ্ট্যগুলি মডিউল নামগুলির একটি তালিকা গ্রহণ করে। তালিকার লাইব্রেরির আপেক্ষিক ক্রমটি অবশ্যই ম্যানিফেস্টের ক্রমের সমান হতে হবে।

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 সংজ্ঞাতে al চ্ছিক লাইব্রেরির জন্য। এই বৈশিষ্ট্যগুলি মডিউল নামগুলির একটি তালিকা গ্রহণ করে। তালিকার লাইব্রেরির আপেক্ষিক ক্রম অবশ্যই ম্যানিফেস্টের মতোই হতে হবে।

বিল্ড ত্রুটি: অজানা গ্রন্থাগার পথ

যদি বিল্ড সিস্টেমটি কোনও <uses-library> ডেক্স জার (একটি বিল্ড-টাইম পাথ অন-হোস্ট বা ডিভাইস অন-ডিভাইস) এর কোনও পথ খুঁজে না পায় তবে এটি সাধারণত বিল্ডটিতে ব্যর্থ হয়। কোনও পথ খুঁজে পেতে ব্যর্থতা নির্দেশ করতে পারে যে গ্রন্থাগারটি কিছু অপ্রত্যাশিত উপায়ে কনফিগার করা হয়েছে। সমস্যাযুক্ত মডিউলটির জন্য ডেক্সপ্রিপ্ট অক্ষম করে অস্থায়ীভাবে বিল্ডটি ঠিক করুন।

অ্যান্ড্রয়েড.বিপি (মডিউল বৈশিষ্ট্য):

enforce_uses_libs: false,
dex_preopt: {
    enabled: false,
},

অ্যান্ড্রয়েড.এমকে (মডিউল ভেরিয়েবল):

LOCAL_ENFORCE_USES_LIBRARIES := false
LOCAL_DEX_PREOPT := false

কোনও অসমর্থিত পরিস্থিতি তদন্ত করতে একটি বাগ ফাইল করুন।

বিল্ড ত্রুটি: অনুপস্থিত গ্রন্থাগার নির্ভরতা

মডিউল ওয়াইয়ের ম্যানিফেস্ট থেকে y এর জন্য বিল্ড ফাইলটিতে <uses-library> এক্স যুক্ত করার প্রয়াস অনুপস্থিত নির্ভরতা, এক্স এর কারণে বিল্ড ত্রুটি হতে পারে, এক্স।

এটি অ্যান্ড্রয়েড.বিপি মডিউলগুলির জন্য একটি নমুনা ত্রুটি বার্তা:

"Y" depends on undefined module "X"

এটি অ্যান্ড্রয়েড.এমকে মডিউলগুলির জন্য একটি নমুনা ত্রুটি বার্তা:

'.../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 নামের মডিউলটি একটি <uses-library> লাইব্রেরি> নামের com.android.X সরবরাহ করে।

এটি Android.bp লাইব্রেরির (মডিউল সম্পত্তি) এর উদাহরণ:

provides_uses_lib: “com.android.X”,

এটি অ্যান্ড্রয়েড.এমকে লাইব্রেরিগুলির জন্য একটি উদাহরণ (মডিউল ভেরিয়েবল):

LOCAL_PROVIDES_USES_LIBRARY := com.android.X

বুট-টাইম সিএলসি মিল নেই

প্রথম বুটে, সিএলসি মেলামেশা সম্পর্কিত বার্তাগুলির জন্য লগক্যাট অনুসন্ধান করুন, নীচে দেখানো হয়েছে:

$ 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: ...

আপনি যদি একটি সিএলসি মেলামেশা সতর্কতা পান তবে ত্রুটিযুক্ত মডিউলটির জন্য একটি ডেক্সপ্ট কমান্ডের সন্ধান করুন। এটি ঠিক করার জন্য, মডিউলগুলির জন্য বিল্ড-টাইম চেকটি পাস হয়েছে তা নিশ্চিত করুন। যদি এটি কাজ না করে, তবে আপনার এমন একটি বিশেষ কেস হতে পারে যা বিল্ড সিস্টেম দ্বারা সমর্থিত নয় (যেমন একটি অ্যাপ্লিকেশন যা অন্য কোনও এপিকে লোড করে, লাইব্রেরি নয়)। বিল্ড সিস্টেমটি সমস্ত কেস পরিচালনা করে না, কারণ বিল্ড টাইমে অ্যাপটি রানটাইমে কী লোড হয় তা নিশ্চিতভাবে জানা অসম্ভব।

ক্লাস লোডার প্রসঙ্গ

সিএলসি একটি গাছের মতো কাঠামো যা শ্রেণি-লোডার শ্রেণিবিন্যাসকে বর্ণনা করে। বিল্ড সিস্টেমটি একটি সংকীর্ণ অর্থে সিএলসি ব্যবহার করে (এটি কেবলমাত্র লাইব্রেরিগুলিকে কভার করে, এপিকে বা কাস্টম-শ্রেণীর লোডার নয়): এটি লাইব্রেরির একটি গাছ যা কোনও গ্রন্থাগার বা অ্যাপের সমস্ত <uses-library> লাইব্রেরি> নির্ভরতাগুলির ট্রানজিটিভ ক্লোজারকে উপস্থাপন করে। একটি সিএলসির টপলভেল উপাদানগুলি হ'ল সরাসরি <uses-library> নির্ভরতা যা ম্যানিফেস্টে নির্দিষ্ট করা হয় (ক্লাসপথ)। একটি সিএলসি গাছের প্রতিটি নোড একটি <uses-library> নোড যা এর নিজস্ব <uses-library> সাব-নোড থাকতে পারে।

কারণ <uses-library> নির্ভরতাগুলি একটি নির্দেশিত অ্যাসাইক্লিক গ্রাফ, এবং অগত্যা কোনও গাছ নয়, সিএলসি একই লাইব্রেরির জন্য একাধিক সাবট্রি থাকতে পারে। অন্য কথায়, সিএলসি হ'ল একটি গাছের কাছে নির্ভরতা গ্রাফ "উন্মুক্ত"। সদৃশটি কেবল একটি যৌক্তিক স্তরে; প্রকৃত অন্তর্নিহিত ক্লাস লোডারগুলি সদৃশ নয় (রানটাইমে প্রতিটি লাইব্রেরির জন্য একক শ্রেণির লোডার উদাহরণ রয়েছে)।

লাইব্রেরি বা অ্যাপ্লিকেশন দ্বারা ব্যবহৃত জাভা ক্লাসগুলি সমাধান করার সময় সিএলসি লাইব্রেরির সন্ধান ক্রমকে সংজ্ঞায়িত করে। লুকআপ অর্ডারটি গুরুত্বপূর্ণ কারণ গ্রন্থাগারগুলিতে ডুপ্লিকেট ক্লাস থাকতে পারে এবং ক্লাসটি প্রথম ম্যাচে সমাধান করা হয়।

ডিভাইসে (রান-টাইম) সিএলসি

PackageManager ( frameworks/base ) ডিভাইস অন জাভা মডিউলটি লোড করতে একটি সিএলসি তৈরি করে। এটি শীর্ষ স্তরের সিএলসি উপাদান হিসাবে মডিউলটির ম্যানিফেস্টে <uses-library> ট্যাগগুলিতে তালিকাভুক্ত গ্রন্থাগারগুলি যুক্ত করে।

প্রতিটি ব্যবহৃত লাইব্রেরির জন্য, PackageManager তার সমস্ত <uses-library> নির্ভরতা (সেই লাইব্রেরির ম্যানিফেস্টে ট্যাগ হিসাবে নির্দিষ্ট) পায় এবং প্রতিটি নির্ভরতার জন্য একটি নেস্টেড সিএলসি যুক্ত করে। এই প্রক্রিয়াটি পুনরাবৃত্তভাবে অব্যাহত থাকে যতক্ষণ না নির্মিত সিএলসি গাছের সমস্ত পাতার নোডগুলি <uses-library> নির্ভরতা ছাড়াই লাইব্রেরি হয়।

PackageManager কেবল ভাগ করা গ্রন্থাগারগুলি সম্পর্কে সচেতন। এই ব্যবহারে ভাগ করা সংজ্ঞাটি তার স্বাভাবিক অর্থ থেকে পৃথক (যেমন ভাগ করা বনাম স্ট্যাটিক হিসাবে)। অ্যান্ড্রয়েডে, জাভা শেয়ার্ড লাইব্রেরিগুলি হ'ল এক্সএমএল কনফিগারেশনে তালিকাভুক্ত যা ডিভাইস ( /system/etc/permissions/platform.xml ) ইনস্টল করা হয়। প্রতিটি এন্ট্রিতে একটি ভাগ করা লাইব্রেরির নাম, তার ডেক্স জার ফাইলের একটি পথ এবং নির্ভরতাগুলির একটি তালিকা রয়েছে (অন্যান্য ভাগ করা লাইব্রেরি যা এটি রানটাইমে ব্যবহার করে এবং এর ম্যানিফেস্টে <uses-library> ট্যাগগুলিতে নির্দিষ্ট করে) থাকে।

অন্য কথায়, দুটি তথ্যের উত্স রয়েছে যা PackageManager রানটাইমে সিএলসি তৈরি করতে দেয়: <uses-library> লাইব্রেরি> ম্যানিফেস্টে ট্যাগগুলি এবং এক্সএমএল কনফিগারেশনে লাইব্রেরির নির্ভরতা ভাগ করে নেওয়া হয়।

অন-হোস্ট (বিল্ড-টাইম) সিএলসি

কোনও লাইব্রেরি বা অ্যাপ্লিকেশন লোড করার সময় কেবল সিএলসির প্রয়োজন হয় না, এটি একটি সংকলন করার সময়ও প্রয়োজন। সংকলনটি অন-ডিভাইস (ডেক্সোপ্ট) বা বিল্ডের সময় (ডেক্সপ্রিপ্ট) ঘটতে পারে। যেহেতু ডেক্সোপ্টটি ডিভাইস অন-ডিভাইস হয়, তাই এটিতে PackageManager (প্রকাশ এবং লাইব্রেরির নির্ভরতা) এর মতো একই তথ্য রয়েছে। ডেক্সপ্রিপ্ট অবশ্য অন-হোস্ট এবং সম্পূর্ণ ভিন্ন পরিবেশে স্থান নেয় এবং এটি বিল্ড সিস্টেম থেকে একই তথ্য পেতে হবে।

সুতরাং, ডেক্সপ্রিপ্ট দ্বারা ব্যবহৃত বিল্ড-টাইম সিএলসি এবং PackageManager দ্বারা ব্যবহৃত রান-টাইম সিএলসি একই জিনিস, তবে দুটি ভিন্ন উপায়ে গণনা করা হয়েছে।

বিল্ড-টাইম এবং রান-টাইম সিএলসিএসকে অবশ্যই মিলে যেতে হবে, অন্যথায় ডেক্সপ্রিপ্ট দ্বারা নির্মিত এওটি-সংমিশ্রিত কোডটি প্রত্যাখ্যানিত হয়। বিল্ড-টাইম এবং রান-টাইম সিএলসিএসের সমতা যাচাই করতে, ডেক্স 2 ওট সংকলকটি *.odex ফাইলগুলিতে (ওএটি ফাইল শিরোনামের classpath ক্ষেত্রে) বিল্ড-টাইম সিএলসি রেকর্ড করে। সঞ্চিত সিএলসি সন্ধান করতে, এই কমান্ডটি ব্যবহার করুন:

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

বিল্ড-টাইম এবং রান-টাইম সিএলসি মেলানো বুট চলাকালীন লগক্যাটে রিপোর্ট করা হয়েছে। এই কমান্ডটি দিয়ে এটি অনুসন্ধান করুন:

logcat | grep -E 'ClassLoaderContext [az ]+ mismatch'

অমিলটি পারফরম্যান্সের জন্য খারাপ, কারণ এটি লাইব্রেরি বা অ্যাপ্লিকেশনটিকে ডেক্সোপ্ট করা বা অপ্টিমাইজেশন ছাড়াই চালাতে বাধ্য করে (উদাহরণস্বরূপ, অ্যাপ্লিকেশনটির কোডটি এপিকে থেকে স্মৃতিতে উত্তোলনের প্রয়োজন হতে পারে, এটি একটি খুব ব্যয়বহুল অপারেশন)।

একটি ভাগ করা লাইব্রেরি হয় al চ্ছিক বা প্রয়োজনীয় হতে পারে। ডেক্সপ্রিপ্ট দৃষ্টিকোণ থেকে, প্রয়োজনীয় লাইব্রেরি অবশ্যই বিল্ড টাইমে উপস্থিত থাকতে হবে (এর অনুপস্থিতি একটি বিল্ড ত্রুটি)। একটি al চ্ছিক গ্রন্থাগারটি বিল্ড টাইমে উপস্থিত বা অনুপস্থিত থাকতে পারে: যদি উপস্থিত থাকে তবে এটি সিএলসিতে যুক্ত করা হয়েছে, ডেক্স 2 এওটি -তে পাস করা হয়েছে এবং *.odex ফাইলে রেকর্ড করা হয়েছে। যদি কোনও al চ্ছিক লাইব্রেরি অনুপস্থিত থাকে তবে এটি এড়ানো যায় এবং সিএলসিতে যুক্ত হয় না। যদি বিল্ড-টাইম এবং রান-টাইম স্ট্যাটাসের মধ্যে কোনও মিল নেই (al চ্ছিক গ্রন্থাগারটি একটি ক্ষেত্রে উপস্থিত থাকে তবে অন্যটি নয়), তবে বিল্ড-টাইম এবং রান-টাইম সিএলসিগুলি মেলে না এবং সংকলিত কোডটি প্রত্যাখ্যানিত হয়।

উন্নত বিল্ড সিস্টেমের বিশদ (ম্যানিফেস্ট ফিক্সার)

কখনও কখনও <uses-library> ট্যাগগুলি কোনও গ্রন্থাগার বা অ্যাপ্লিকেশনটির উত্স ম্যানিফেস্ট থেকে অনুপস্থিত থাকে। এটি ঘটতে পারে, উদাহরণস্বরূপ, যদি লাইব্রেরি বা অ্যাপের ট্রানজিটিভ নির্ভরতাগুলির মধ্যে একটি অন্য <uses-library> ট্যাগ ব্যবহার শুরু করে এবং লাইব্রেরি বা অ্যাপ্লিকেশনটির ম্যানিফেস্ট এটি অন্তর্ভুক্ত করার জন্য আপডেট না করে।

সোং লাইব্রেরি বা অ্যাপ্লিকেশনটির ট্রানজিটিভ নির্ভরতা বন্ধের এসডিকে লাইব্রেরি হিসাবে স্বয়ংক্রিয়ভাবে প্রদত্ত গ্রন্থাগার বা অ্যাপের জন্য কিছু অনুপস্থিত <ব্যবহার <uses-library> ট্যাগগুলি গণনা করতে পারে। বন্ধটি প্রয়োজন কারণ লাইব্রেরি (বা অ্যাপ্লিকেশন) একটি স্ট্যাটিক লাইব্রেরির উপর নির্ভর করতে পারে যা কোনও এসডিকে লাইব্রেরির উপর নির্ভর করে এবং সম্ভবত আবার অন্য লাইব্রেরির মাধ্যমে ট্রানজিটিভভাবে নির্ভর করতে পারে।

সমস্ত <uses-library> ট্যাগগুলি এইভাবে গণনা করা যায় না, তবে যখন সম্ভব হয় তখন সংকে স্বয়ংক্রিয়ভাবে ম্যানিফেস্ট এন্ট্রি যুক্ত করা পছন্দ করা যায়; এটি কম ত্রুটি-প্রবণ এবং রক্ষণাবেক্ষণকে সহজ করে তোলে। উদাহরণস্বরূপ, যখন অনেক অ্যাপ্লিকেশন একটি স্ট্যাটিক লাইব্রেরি ব্যবহার করে যা একটি নতুন <uses-library> নির্ভরতা যুক্ত করে, সমস্ত অ্যাপ্লিকেশন অবশ্যই আপডেট করতে হবে, যা বজায় রাখা কঠিন।