आर्ट टीआई

Android 8.0 और इसके बाद के वर्शन में, ART टूल इंटरफ़ेस (ART TI) कुछ रनटाइम इंटरनल को दिखाता है. साथ ही, प्रोफ़ाइलर और डीबगर को ऐप्लिकेशन के रनटाइम व्यवहार पर असर डालने की सुविधा देता है. इसका इस्तेमाल, बेहतरीन परफ़ॉर्मेंस टूल लागू करने के लिए किया जा सकता है. ये टूल, अन्य प्लैटफ़ॉर्म पर नेटिव एजेंट लागू करने के लिए उपलब्ध कराए जाते हैं.

रनटाइम के इंटरनल, उन एजेंट को दिखाए जाते हैं जिन्हें रनटाइम प्रोसेस में लोड किया गया है. ये डायरेक्ट कॉल और कॉलबैक के ज़रिए ART से संपर्क करते हैं. रनटाइम, एक से ज़्यादा एजेंट के साथ काम करता है, ताकि अलग-अलग ऑर्थोगोनल-प्रोफ़ाइलिंग से जुड़ी समस्याओं को अलग किया जा सके. एजेंट, रनटाइम शुरू होने पर (dalvikvm या app_process का इस्तेमाल करने पर) या पहले से चल रही प्रोसेस से जुड़े हो सकते हैं.

ऐप्लिकेशन और रनटाइम के व्यवहार को इंस्ट्रूमेंट करने और उसमें बदलाव करने की सुविधा काफ़ी असरदार है. इसलिए, ART TI में सुरक्षा के दो उपाय इंटिग्रेट किए गए हैं:

  • पहला, एजेंट इंटरफ़ेस, JVMTI को एक्सपोज़ करने वाले कोड को रनटाइम प्लग इन के तौर पर लागू किया जाता है, न कि रनटाइम के मुख्य कॉम्पोनेंट के तौर पर. प्लग इन लोड करने पर पाबंदी लगाई जा सकती है, ताकि एजेंट किसी भी इंटरफ़ेस पॉइंट को ढूंढने से रोके जा सकें.
  • दूसरा, ActivityManager क्लास और रनटाइम प्रोसेस, दोनों ही एजेंट को सिर्फ़ डीबग किए जा सकने वाले ऐप्लिकेशन से अटैच करने की अनुमति देते हैं. डीबग किए जा सकने वाले ऐप्लिकेशन का विश्लेषण और जांच करने के लिए, डेवलपर ने इन पर हस्ताक्षर किए हैं. साथ ही, इन्हें आम उपयोगकर्ताओं को डिस्ट्रिब्यूट नहीं किया जाता. Google Play Store, डीबग किए जा सकने वाले ऐप्लिकेशन को डिस्ट्रिब्यूट करने की अनुमति नहीं देता. इससे यह पक्का होता है कि सामान्य ऐप्लिकेशन (इसमें मुख्य कॉम्पोनेंट भी शामिल हैं) को मैनिप्युलेट या इंस्ट्रूमेंट नहीं किया जा सकता.

डिज़ाइन

इंस्ट्रूमेंट किए गए ऐप्लिकेशन में सामान्य फ़्लो और इंटरकनेक्शन, पहली इमेज में दिखाया गया है.

इंस्ट्रूमेंट किए गए ऐप्लिकेशन में फ़्लो और इंटरकनेक्शन
पहली इमेज. इंस्ट्रुमेंट किए गए ऐप्लिकेशन का फ़्लो और इंटरकनेक्शन

ART प्लग इन libopenjdkjvmti, ART TI को दिखाता है. इसे प्लैटफ़ॉर्म की ज़रूरतों और सीमाओं को ध्यान में रखकर डिज़ाइन किया गया है:

  • क्लास को फिर से परिभाषित करने की सुविधा, Dex फ़ाइलों पर आधारित होती है. इनमें क्लास फ़ाइलों के बजाय, सिर्फ़ एक क्लास की परिभाषा होती है.
  • इंस्ट्रुमेंटेशन और फिर से परिभाषित करने के लिए, Java-language API को ज़ाहिर नहीं किया जाता.

ART TI, Android Studio के प्रोफ़ाइलर के साथ भी काम करता है.

एजेंट लोड करना या अटैच करना

रनटाइम स्टार्टअप के दौरान एजेंट को अटैच करने के लिए, JVMTI प्लगिन और दिए गए एजेंट, दोनों को लोड करने के लिए इस निर्देश का इस्तेमाल करें:

dalvikvm -Xplugin:libopenjdkjvmti.so -agentpath:/path/to/agent/libagent.so …

रनटाइम के शुरू होने पर एजेंट लोड होने पर, सुरक्षा के उपाय लागू नहीं होते. इसलिए, ध्यान रखें कि मैन्युअल तरीके से शुरू किए गए रनटाइम में, सुरक्षा के उपायों के बिना पूरी तरह बदलाव किया जा सकता है. (इससे एआरटी टेस्टिंग की अनुमति मिलती है.)

ध्यान दें: यह किसी डिवाइस पर मौजूद सामान्य ऐप्लिकेशन (इसमें सिस्टम सर्वर भी शामिल है) पर लागू नहीं होता. ऐप्लिकेशन, पहले से चल रहे ज़ाइगोट से फ़ोक्ड किए जाते हैं. साथ ही, ज़ाइगोट प्रोसेस को एजेंट लोड करने की अनुमति नहीं है.

पहले से चल रहे ऐप्लिकेशन में एजेंट जोड़ने के लिए, इस कमांड का इस्तेमाल करें:

adb shell cmd activity attach-agent [process]
/path/to/agent/libagent.so[=agent-options]

अगर JVMTI प्लग इन अब तक लोड नहीं हुआ है, तो एजेंट जोड़ने पर, प्लग इन और एजेंट लाइब्रेरी, दोनों लोड हो जाती हैं.

एजेंट को सिर्फ़ ऐसे ऐप्लिकेशन से जोड़ा जा सकता है जो डीबग किया जा सकता है के तौर पर मार्क किया गया हो. यह ऐप्लिकेशन के मेनिफ़ेस्ट का हिस्सा होता है. इसमें ऐप्लिकेशन नोड पर एट्रिब्यूट android:debuggable को true पर सेट किया जाता है. किसी एजेंट को अटैच करने की अनुमति देने से पहले, ActivityManager क्लास और एआरटी, दोनों जांच करते हैं. ActivityManager क्लास, ऐप्लिकेशन की मौजूदा जानकारी की जांच करती है. यह जानकारी, PackageManager क्लास के डेटा से मिलती है. यह जांच यह पता लगाने के लिए की जाती है कि ऐप्लिकेशन को डीबग किया जा सकता है या नहीं. साथ ही, रनटाइम इसकी मौजूदा स्थिति की जांच करता है. यह स्थिति, ऐप्लिकेशन शुरू होने पर सेट की गई थी.

एजेंट की जगह की जानकारी

रनटाइम को मौजूदा प्रोसेस में एजेंट लोड करने होंगे, ताकि एजेंट सीधे तौर पर उससे कनेक्ट हो सके और उससे कम्यूनिकेट कर सके. एजेंट जिस जगह से आता है, एआरटी को इससे कोई फ़र्क़ नहीं पड़ता. स्ट्रिंग का इस्तेमाल dlopen कॉल के लिए किया जाता है. फ़ाइल सिस्टम की अनुमतियां और SELinux नीतियां, असल लोडिंग पर पाबंदी लगाती हैं.

ऐसे एजेंट डिलीवर करने के लिए जिन्हें डीबग किए जा सकने वाले ऐप्लिकेशन से चलाया जा सकता है, यह तरीका अपनाएं:

  • एजेंट को ऐप्लिकेशन के APK की लाइब्रेरी डायरेक्ट्री में जोड़ें.
  • एजेंट को ऐप्लिकेशन की डेटा डायरेक्ट्री में कॉपी करने के लिए, run-as का इस्तेमाल करें.

API

android.os.Debug में यह तरीका जोड़ा गया था.

/**
     * Attach a library as a jvmti agent to the current runtime, with the given classloader
     * determining the library search path.
     * Note: agents may only be attached to debuggable apps. Otherwise, this function will
     * throw a SecurityException.
     *
     * @param library the library containing the agent.
     * @param options the options passed to the agent.
     * @param classLoader the classloader determining the library search path.
     *
     * @throws IOException if the agent could not be attached.
     * @throws a SecurityException if the app is not debuggable.
     */
    public static void attachJvmtiAgent(@NonNull String library, @Nullable String options,
            @Nullable ClassLoader classLoader) throws IOException {

अन्य Android API

attach-agent कमांड सार्वजनिक तौर पर दिखता है. यह कमांड, चल रही प्रोसेस में JVMTI एजेंट को जोड़ता है:

adb shell 'am attach-agent com.example.android.displayingbitmaps
\'/data/data/com.example.android.displayingbitmaps/code_cache/libfieldnulls.so=Ljava/lang/Class;.name:Ljava/lang/String;\''

am start -P और am start-profiler/stop-profiler निर्देश, attach-agent निर्देश से मिलते-जुलते हैं.

JVMTI

यह सुविधा, एजेंट (नेटिव कोड) को JVMTI API दिखाती है. इसकी मुख्य सुविधाओं में ये शामिल हैं:

  • किसी क्लास को फिर से तय करना.
  • ऑब्जेक्ट के ऐलोकेशन और कचरा इकट्ठा करने की प्रोसेस को ट्रैक करना.
  • ऑब्जेक्ट के रेफ़रंस ट्री का पालन करके, हेप में मौजूद सभी ऑब्जेक्ट पर बारी-बारी से जाना.
  • Java कॉल स्टैक की जांच करना.
  • सभी थ्रेड को निलंबित (और फिर से शुरू) करना.

Android के अलग-अलग वर्शन पर, अलग-अलग सुविधाएं उपलब्ध हो सकती हैं.

इनके साथ काम करता है

इस सुविधा के लिए, कोर रनटाइम की ज़रूरत होती है. यह सुविधा सिर्फ़ Android 8.0 और उसके बाद के वर्शन पर उपलब्ध है. डिवाइस बनाने वाली कंपनियों को इस सुविधा को लागू करने के लिए, डिवाइस में कोई बदलाव करने की ज़रूरत नहीं है. यह AOSP का हिस्सा है.

पुष्टि करें

CTS, Android 8 और उसके बाद के वर्शन पर इन चीज़ों की जांच करता है:

  • यह जांच करता है कि एजेंट, डीबग किए जा सकने वाले ऐप्लिकेशन से जुड़ते हैं या नहीं. साथ ही, यह भी जांच करता है कि वे डीबग नहीं किए जा सकने वाले ऐप्लिकेशन से जुड़ते हैं या नहीं.
  • लागू किए गए सभी JVMTI एपीआई की जांच करता है
  • यह जांच करता है कि एजेंट के लिए बाइनरी इंटरफ़ेस सही तरीके से काम कर रहा है या नहीं

Android 9 और उसके बाद के वर्शन के लिए, कुछ और टेस्ट जोड़े गए हैं. साथ ही, उन्हें उन रिलीज़ के लिए सीटीएस टेस्ट में शामिल किया गया है.