ศิลปะ TI

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

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

เนื่องจากความสามารถในการวัดและแก้ไขลักษณะการทํางานของแอปและรันไทม์มีประสิทธิภาพสูงมาก เราจึงผสานรวมมาตรการด้านความปลอดภัย 2 ประการไว้ใน ART TI ดังนี้

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

การออกแบบ

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

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

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

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

นอกจากนี้ ART TI ยังรองรับเครื่องมือวิเคราะห์โปรไฟล์ของ Android Studio ด้วย

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

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

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

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

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

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

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

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

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

สถานที่ตั้งของตัวแทน

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

API อื่นๆ ของ Android

คำสั่ง 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 ขึ้นไป

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

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