ART TI

ใน Android 8.0 ขึ้นไป ART Tooling Interface (ART TI) จะเปิดเผยรันไทม์ภายในบางอย่าง และช่วยให้ผู้สร้างโปรไฟล์และตัวดีบั๊กมีอิทธิพลต่อพฤติกรรมรันไทม์ของแอปได้ ซึ่งสามารถใช้เพื่อใช้เครื่องมือประสิทธิภาพที่ล้ำสมัยซึ่งมีให้สำหรับการนำเอเจนต์ดั้งเดิมไปใช้งานบนแพลตฟอร์มอื่น

ภายในรันไทม์จะถูกเปิดเผยต่อเอเจนต์ที่ถูกโหลดเข้าสู่กระบวนการรันไทม์ สิ่งเหล่านี้สื่อสารกับ ART ผ่านการโทรโดยตรงและการโทรกลับ รันไทม์รองรับเอเจนต์หลายตัว เพื่อให้สามารถแยกข้อกังวลในการทำโปรไฟล์มุมฉากที่แตกต่างกันได้ เอเจนต์อาจถูกจัดหาเมื่อรันไทม์เริ่มต้น (เมื่อมีการเรียกใช้ dalvikvm หรือ app_process ) หรือแนบไปกับกระบวนการที่กำลังทำงานอยู่

เนื่องจากความสามารถในการวัดและแก้ไขแอปและพฤติกรรมรันไทม์นั้นทรงพลังมาก จึงมีการรวมมาตรการด้านความปลอดภัยสองประการเข้ากับ ART TI:

  • ขั้นแรก โค้ดที่แสดงอินเทอร์เฟซเอเจนต์ JVMTI จะถูกนำไปใช้เป็นปลั๊กอินรันไทม์ ไม่ใช่องค์ประกอบหลักของรันไทม์ การโหลดปลั๊กอินอาจถูกจำกัด เพื่อให้สามารถบล็อกเอเจนต์ไม่ให้ค้นหาจุดอินเทอร์เฟซใดๆ ได้
  • ประการที่สอง ทั้งคลาส ActivityManager และกระบวนการรันไทม์อนุญาตให้ตัวแทนแนบกับแอปที่แก้ไขข้อบกพร่องได้เท่านั้น แอปที่แก้ไขข้อบกพร่องได้ลงนามโดยนักพัฒนาแล้ว เพื่อรับการวิเคราะห์และใช้เครื่องมือ และจะไม่เผยแพร่ให้กับผู้ใช้ปลายทาง Google Play Store ไม่อนุญาตให้เผยแพร่แอปที่แก้ไขข้อบกพร่องได้ เพื่อให้แน่ใจว่าแอปปกติ (รวมถึงส่วนประกอบหลัก) จะไม่สามารถติดตั้งหรือจัดการได้

ออกแบบ

โฟลว์ทั่วไปและการเชื่อมต่อโครงข่ายในแอปที่มีเครื่องมือแสดงไว้ใน รูปที่ 1

Flow and interconnection in an instrumented app
รูปที่ 1 โฟลว์และการเชื่อมต่อของแอปที่มีเครื่องมือวัด

ปลั๊กอิน ART libopenjdkjvmti เปิดเผย ART TI ซึ่งได้รับการออกแบบมาเพื่อรองรับความต้องการและข้อจำกัดของแพลตฟอร์ม:

  • การกำหนดคลาสใหม่จะขึ้นอยู่กับไฟล์ Dex ซึ่งมีคำจำกัดความคลาสเดียวเท่านั้น แทนที่จะเป็นไฟล์คลาส
  • API ภาษา Java สำหรับการใช้เครื่องมือและการกำหนดนิยามใหม่จะไม่ถูกเปิดเผย

ART TI ยังรองรับผู้สร้างโปรไฟล์ Android Studio

โหลดหรือแนบตัวแทน

หากต้องการแนบเอเจนต์เมื่อเริ่มต้นรันไทม์ ให้ใช้คำสั่งนี้เพื่อโหลดทั้งปลั๊กอิน JVMTI และเอเจนต์ที่กำหนด:

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

ไม่มีมาตรการด้านความปลอดภัยเมื่อมีการโหลดเอเจนต์เมื่อเริ่มต้นรันไทม์ ดังนั้น โปรดทราบว่ารันไทม์ที่เริ่มต้นด้วยตนเองทำให้สามารถปรับเปลี่ยนได้เต็มรูปแบบโดยไม่มีมาตรการด้านความปลอดภัย (ซึ่งช่วยให้สามารถทดสอบ ART ได้)

หมายเหตุ: สิ่งนี้ใช้ไม่ได้กับแอปปกติ (รวมถึงเซิร์ฟเวอร์ระบบ) บนอุปกรณ์ แอปถูกแยกจากไซโกตที่ทำงานอยู่แล้ว และกระบวนการไซโกตไม่ได้รับอนุญาตให้โหลดเอเจนต์

หากต้องการแนบตัวแทนกับแอปที่กำลังทำงานอยู่ ให้ใช้คำสั่งนี้:

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

หากยังไม่ได้โหลดปลั๊กอิน JVMTI การแนบเอเจนต์จะโหลดทั้งปลั๊กอินและไลบรารีเอเจนต์

ตัวแทนสามารถแนบกับแอปที่ทำงานอยู่ซึ่งทำเครื่องหมายว่า แก้ไขข้อบกพร่องได้ เท่านั้น (ส่วนหนึ่งของรายการแอป โดยมีแอตทริบิวต์ android:debuggable ตั้งค่าเป็น true บนโหนดแอป) ทั้งคลาส ActivityManager และ ART ทำการตรวจสอบก่อนที่จะอนุญาตให้แนบเอเจนต์ คลาส ActivityManager จะตรวจสอบข้อมูลแอปปัจจุบัน (ที่ได้มาจากข้อมูลคลาส PackageManager ) เพื่อดูสถานะที่สามารถแก้ไขข้อบกพร่องได้ และรันไทม์จะตรวจสอบสถานะปัจจุบันซึ่งตั้งค่าไว้เมื่อแอปเริ่มทำงาน

ที่ตั้งตัวแทน

รันไทม์จำเป็นต้องโหลดเอเจนต์เข้าสู่กระบวนการปัจจุบัน เพื่อให้เอเจนต์สามารถเชื่อมโยงและสื่อสารกับเอเจนต์ได้โดยตรง ART เองนั้นไม่เชื่อเรื่องพระเจ้าเกี่ยวกับสถานที่เฉพาะที่ตัวแทนมา สตริงถูกใช้สำหรับการโทร 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 อื่นๆ

คำสั่งแนบเอเจนต์จะปรากฏต่อสาธารณะ คำสั่งนี้แนบเอเจนต์ 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 คล้ายกับคำสั่งแนบเอเจนต์

เจวีเอ็มทีไอ

คุณลักษณะนี้เปิดเผย JVMTI API แก่เอเจนต์ (โค้ดเนทิฟ) ความสามารถที่สำคัญ ได้แก่ :

  • นิยามคลาสใหม่
  • ติดตามการจัดสรรวัตถุและการรวบรวมขยะ
  • วนซ้ำวัตถุทั้งหมดในฮีป ตามแผนผังอ้างอิงของวัตถุ
  • การตรวจสอบสแต็กการเรียก Java
  • ระงับ (และดำเนินการต่อ) เธรดทั้งหมด

ความสามารถที่แตกต่างกันอาจมีให้ใช้งานบน Android เวอร์ชันที่แตกต่างกัน

ความเข้ากันได้

คุณลักษณะนี้ต้องการการสนับสนุนรันไทม์หลักซึ่งมีเฉพาะใน Android 8.0 ขึ้นไปเท่านั้น ผู้ผลิตอุปกรณ์ไม่จำเป็นต้องทำการเปลี่ยนแปลงใดๆ เพื่อใช้งานฟีเจอร์นี้ เป็นส่วนหนึ่งของ AOSP

การตรวจสอบ

CTS ทดสอบสิ่งต่อไปนี้บน Android 8 และสูงกว่า:

  • ทดสอบว่าเอเจนต์แนบกับแอปที่แก้ไขข้อบกพร่องได้ และไม่สามารถแนบกับแอปที่แก้ไขข้อบกพร่องไม่ได้
  • ทดสอบ JVMTI API ที่ใช้งานทั้งหมด
  • ทดสอบว่าอินเทอร์เฟซไบนารี่สำหรับเอเจนต์มีเสถียรภาพ

มีการเพิ่มการทดสอบเพิ่มเติมใน Android 9 ขึ้นไป และรวมอยู่ในการทดสอบ CTS สำหรับรุ่นเหล่านั้น