ใน Android 8.0 ขึ้นไป ART Tooling Interface (ART TI) จะเปิดเผยรันไทม์ภายในบางอย่าง และช่วยให้ผู้สร้างโปรไฟล์และตัวดีบั๊กมีอิทธิพลต่อพฤติกรรมรันไทม์ของแอปได้ ซึ่งสามารถใช้เพื่อใช้เครื่องมือประสิทธิภาพที่ล้ำสมัยซึ่งมีให้สำหรับการนำเอเจนต์ดั้งเดิมไปใช้งานบนแพลตฟอร์มอื่น
ภายในรันไทม์จะถูกเปิดเผยต่อเอเจนต์ที่ถูกโหลดเข้าสู่กระบวนการรันไทม์ สิ่งเหล่านี้สื่อสารกับ ART ผ่านการโทรโดยตรงและการโทรกลับ รันไทม์รองรับเอเจนต์หลายตัว เพื่อให้สามารถแยกข้อกังวลในการทำโปรไฟล์มุมฉากที่แตกต่างกันได้ เอเจนต์อาจถูกจัดหาเมื่อรันไทม์เริ่มต้น (เมื่อมีการเรียกใช้ dalvikvm
หรือ app_process
) หรือแนบไปกับกระบวนการที่กำลังทำงานอยู่
เนื่องจากความสามารถในการวัดและแก้ไขแอปและพฤติกรรมรันไทม์นั้นทรงพลังมาก จึงมีการรวมมาตรการด้านความปลอดภัยสองประการเข้ากับ ART TI:
- ขั้นแรก โค้ดที่แสดงอินเทอร์เฟซเอเจนต์ JVMTI จะถูกนำไปใช้เป็นปลั๊กอินรันไทม์ ไม่ใช่องค์ประกอบหลักของรันไทม์ การโหลดปลั๊กอินอาจถูกจำกัด เพื่อให้สามารถบล็อกเอเจนต์ไม่ให้ค้นหาจุดอินเทอร์เฟซใดๆ ได้
- ประการที่สอง ทั้งคลาส
ActivityManager
และกระบวนการรันไทม์อนุญาตให้ตัวแทนแนบกับแอปที่แก้ไขข้อบกพร่องได้เท่านั้น แอปที่แก้ไขข้อบกพร่องได้ลงนามโดยนักพัฒนาแล้ว เพื่อรับการวิเคราะห์และใช้เครื่องมือ และจะไม่เผยแพร่ให้กับผู้ใช้ปลายทาง Google Play Store ไม่อนุญาตให้เผยแพร่แอปที่แก้ไขข้อบกพร่องได้ เพื่อให้แน่ใจว่าแอปปกติ (รวมถึงส่วนประกอบหลัก) จะไม่สามารถติดตั้งหรือจัดการได้
ออกแบบ
โฟลว์ทั่วไปและการเชื่อมต่อโครงข่ายในแอปที่มีเครื่องมือแสดงไว้ใน รูปที่ 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 สำหรับรุ่นเหล่านั้น