บันทึกฮีปดัมพ์เพื่อดูว่าออบเจ็กต์ใดในแอปที่ใช้หน่วยความจํา ณ เวลาบันทึก และระบุการรั่วไหลของหน่วยความจําหรือลักษณะการจัดสรรหน่วยความจําที่ทําให้แอปกระตุก ค้าง หรือแม้แต่ขัดข้อง ซึ่งจะมีประโยชน์อย่างยิ่งในการถ่ายโอนข้อมูลกองหลังจากเซสชันของผู้ใช้ที่ขยายเวลาออกไป เมื่อระบบอาจแสดงออบเจ็กต์ที่ยังคงอยู่ในหน่วยความจำซึ่งไม่ควรอยู่อีกต่อไป
หน้านี้จะอธิบายเครื่องมือที่ Android Studio มีให้เพื่อรวบรวมและวิเคราะห์กองข้อมูล หรือจะตรวจสอบหน่วยความจำของแอปจากบรรทัดคำสั่งด้วย dumpsys
และดูเหตุการณ์การเก็บขยะ (GC) ใน Logcat ก็ได้
เหตุผลที่ควรวิเคราะห์หน่วยความจําของแอป
Android มีหน่วยความจำที่มีการจัดการ สภาพแวดล้อมการทำงาน - เมื่อ Android ระบุว่า แอปของคุณไม่ได้ใช้ออบเจ็กต์บางอย่างอีกต่อไป เครื่องมือเก็บขยะจะเผยแพร่แอป กลับเข้าไปในฮีป Android มีวิธีการค้นหาหน่วยความจำที่ไม่ได้ใช้อย่างไร ได้รับการปรับปรุงอย่างต่อเนื่อง แต่ในบางกรณีบน Android ทุกเวอร์ชัน ต้องหยุดโค้ดของคุณชั่วคราว ส่วนใหญ่แล้ว การหยุดชั่วคราวนั้นไม่สามารถรับรู้ได้ อย่างไรก็ตาม หากแอปของคุณจัดสรรหน่วยความจำเร็วกว่าที่ระบบจะรวบรวมได้ แอปอาจทำงานล่าช้าขณะที่เครื่องมือรวบรวมหน่วยความจำเพิ่มพื้นที่หน่วยความจำให้เพียงพอสำหรับการจัดสรรของคุณ ความล่าช้าอาจทำให้แอปข้ามเฟรม ความช้าที่มองเห็นได้
แม้ว่าแอปจะไม่แสดงผลช้า แต่หากหน่วยความจำรั่วไหล แอปจะยังรักษาสถานะเดิมไว้ได้ ความทรงจำนั้นแม้จะอยู่ในเบื้องหลัง การทำงานลักษณะนี้อาจทำให้ส่วนที่เหลือทำงานช้าลง ประสิทธิภาพหน่วยความจำของระบบโดยบังคับให้ระบบเก็บข้อมูลขยะที่ไม่จำเป็น กิจกรรม ในที่สุดระบบจะบังคับให้หยุดกระบวนการของแอปเพื่อเรียกคืนหน่วยความจำ จากนั้นเมื่อผู้ใช้กลับไปที่แอป กระบวนการของแอปจะต้องรีสตาร์ท อย่างสิ้นเชิง
ดูข้อมูลเกี่ยวกับแนวทางปฏิบัติด้านการเขียนโปรแกรมที่สามารถลดการใช้หน่วยความจำของแอปได้ที่จัดการหน่วยความจำของแอป
ภาพรวมของฮีปดัมป์
หากต้องการบันทึกฮีปดัมป์ เลือกงานวิเคราะห์การใช้งานหน่วยความจำ (ฮีปดัมป์) (ใช้ Profiler: เรียกใช้ "app" เป็นแบบแก้ไขข้อบกพร่องได้ (ข้อมูลทั้งหมด)) เพื่อบันทึกฮีป ดัมพ์ ขณะถ่ายโอนข้อมูลฮีป ปริมาณหน่วยความจํา Java อาจเพิ่มขึ้นชั่วคราว กรณีนี้เป็นเรื่องปกติเนื่องจากฮีปดัมป์เกิดขึ้นในกระบวนการเดียวกับแอปของคุณและต้องใช้หน่วยความจําบางส่วนเพื่อรวบรวมข้อมูล หลังจากจับภาพ ฮีปดัมป์ คุณจะเห็นสิ่งต่อไปนี้
รายการชั้นเรียนจะแสดงข้อมูลต่อไปนี้
- การจัดสรร: จํานวนการจัดสรรในกอง
ขนาดเนทีฟ: จำนวนหน่วยความจำเนทีฟทั้งหมดที่ใช้โดยออบเจ็กต์ประเภทนี้ (เป็นไบต์) คุณจะเห็นหน่วยความจำที่นี่สำหรับออบเจ็กต์บางรายการที่จัดสรรใน Java เนื่องจาก Android ใช้หน่วยความจำในเครื่องสำหรับคลาสเฟรมเวิร์กบางคลาส เช่น
Bitmap
ขนาดระดับออบเจ็กต์: ปริมาณหน่วยความจำทั้งหมดของ Java ที่ออบเจ็กต์ประเภทนี้ใช้ (ใน ไบต์)
ขนาดที่คงไว้: ขนาดทั้งหมดของหน่วยความจำที่เก็บรักษาไว้เนื่องจากอินสแตนซ์ทั้งหมดของ คลาสนี้ (ในหน่วยไบต์)
ใช้เมนูกองเพื่อกรองกองที่เฉพาะเจาะจง ดังนี้
- กองขยะของแอป (ค่าเริ่มต้น): กองขยะหลักที่แอปจัดสรรหน่วยความจำ
- ฮีปอิมเมจ: อิมเมจเปิดเครื่องของระบบซึ่งมีคลาสที่โหลดไว้ล่วงหน้า ระหว่างเวลาเปิดเครื่อง การจัดสรรในส่วนนี้จะไม่มีการย้ายหรือหายไป
- กอง Zygote: กอง Copy-On-Write ที่แยกกระบวนการแอปออกจากระบบ Android
ใช้เมนูแบบเลื่อนลง "จัดเรียง" เพื่อเลือกวิธีจัดเรียงการจัดสรร ดังนี้
- จัดเรียงตามชั้นเรียน (ค่าเริ่มต้น): จัดกลุ่มการจัดสรรทั้งหมดตามชื่อชั้นเรียน
- จัดเรียงตามแพ็กเกจ: จัดกลุ่มการจัดสรรทั้งหมดตามชื่อแพ็กเกจ
ใช้เมนูแบบเลื่อนลงของชั้นเรียนเพื่อกรองกลุ่มชั้นเรียน ดังนี้
- คลาสทั้งหมด (ค่าเริ่มต้น): แสดงคลาสทั้งหมด รวมถึงคลาสจากไลบรารีและ Dependency
- แสดงกิจกรรม/การรั่วไหลของส่วนย่อย: แสดงคลาสที่ทำให้หน่วยความจำรั่วไหล
- แสดงคลาสโปรเจ็กต์: แสดงเฉพาะคลาสที่โปรเจ็กต์กำหนด
คลิกชื่อคลาสเพื่อเปิดแผงอินสแตนซ์ อินสแตนซ์แต่ละรายการที่แสดงจะมีข้อมูลต่อไปนี้
- ความลึก: จำนวน Hop ที่สั้นที่สุดจากรูท GC ไปยังอินสแตนซ์ที่เลือก
- ขนาดเนทีฟ: ขนาดของอินสแตนซ์นี้ในหน่วยความจําเนทีฟ คอลัมน์นี้ มองเห็นได้สำหรับ Android 7.0 ขึ้นไปเท่านั้น
- ขนาดระดับออบเจ็กต์: ขนาดของอินสแตนซ์นี้ในหน่วยความจำ Java
- ขนาดที่คงไว้: ขนาดของหน่วยความจำที่อินสแตนซ์นี้มีผล (ตาม Dominator Tree)
คลิกอินสแตนซ์เพื่อแสดงรายละเอียดอินสแตนซ์ รวมถึงช่องของอินสแตนซ์
และข้อมูลอ้างอิง ช่องและข้อมูลอ้างอิงประเภททั่วไปเป็นประเภทที่มีโครงสร้าง
อาร์เรย์
,
และข้อมูลพื้นฐาน
ใน Java คลิกขวาที่ช่องหรือการอ้างอิงเพื่อไปยังอินสแตนซ์ที่เชื่อมโยง หรือ
ในซอร์สโค้ด
- ช่อง: แสดงทุกช่องในอินสแตนซ์นี้
- ข้อมูลอ้างอิง: แสดงการอ้างอิงทุกรายการไปยังออบเจ็กต์ที่ไฮไลต์ในส่วน แท็บอินสแตนซ์
ค้นหาการรั่วไหลของหน่วยความจำ
หากต้องการกรองชั้นเรียนที่อาจเกี่ยวข้องกับการรั่วไหลของหน่วยความจำอย่างรวดเร็ว ให้เปิด
เมนูแบบเลื่อนลงของชั้นเรียน แล้วเลือกแสดงการรั่วไหลของกิจกรรม/ส่วนย่อย Android Studio จะแสดงคลาสที่คิดว่าบ่งบอกถึงการรั่วไหลของหน่วยความจำสำหรับอินสแตนซ์ Activity
และ Fragment
ในแอปของคุณ ประเภทข้อมูลซึ่งตัวกรองแสดงมีดังนี้
- อินสแตนซ์
Activity
ที่ถูกทำลายแล้วแต่ยังคงมีการอ้างอิง - อินสแตนซ์
Fragment
ที่ไม่มีFragmentManager
ที่ถูกต้องแต่ยังคงมีการอ้างอิง
โปรดทราบว่าตัวกรองอาจให้ผลบวกลวงในสถานการณ์ต่อไปนี้
- สร้าง
Fragment
แล้วแต่ยังไม่ได้ใช้งาน - ระบบแคช
Fragment
ไว้ แต่ไม่ได้เป็นส่วนหนึ่งของFragmentTransaction
หากต้องการค้นหาการรั่วไหลของหน่วยความจําด้วยตนเอง ให้เรียกดูรายการคลาสและอินสแตนซ์เพื่อค้นหาออบเจ็กต์ที่มีขนาดที่เก็บไว้ขนาดใหญ่ มองหาหน่วยความจําที่รั่วไหลซึ่งเกิดจากสาเหตุต่อไปนี้
- การอ้างอิง
Activity
,Context
,View
,Drawable
และออบเจ็กต์อื่นๆ อยู่ตลอด ซึ่งอาจมีการอ้างอิงถึงคอนเทนเนอร์Activity
หรือContext
- ชั้นเรียนภายในที่ไม่คงที่ เช่น
Runnable
ซึ่งเก็บActivity
ได้ อินสแตนซ์ - แคชที่เก็บออบเจ็กต์ไว้นานกว่าที่จำเป็น
เมื่อคุณพบการรั่วไหลของหน่วยความจำที่อาจเกิดขึ้น ให้ใช้แท็บช่องและข้อมูลอ้างอิง ในรายละเอียดอินสแตนซ์ เพื่อข้ามไปยังบรรทัดของอินสแตนซ์หรือซอร์สโค้ดที่สนใจ
ทริกเกอร์หน่วยความจำที่รั่วสำหรับการทดสอบ
หากต้องการวิเคราะห์การใช้งานหน่วยความจำ คุณควรเขียนโค้ดของแอปให้เข้มงวดและพยายามบังคับใช้หน่วยความจำ การรั่วไหล วิธีหนึ่งในการกระตุ้นให้เกิดการรั่วไหลของหน่วยความจำในแอปคือการปล่อยให้แอปทำงานไปสักพักก่อนตรวจสอบกอง การรั่วไหลอาจเพิ่มขึ้นไปยังด้านบนของการจองในกอง อย่างไรก็ตาม ยิ่งการรั่วไหลมีขนาดเล็ก คุณก็จะต้องเรียกใช้แอปนานขึ้นเพื่อดูการรั่วไหล
นอกจากนี้ คุณยังทริกเกอร์การรั่วไหลของหน่วยความจำได้ด้วยวิธีใดวิธีหนึ่งต่อไปนี้
- หมุนอุปกรณ์จากแนวตั้งเป็นแนวนอนและหมุนกลับอีกครั้งหลายๆ ครั้ง
เมื่ออยู่ในสถานะกิจกรรมที่ต่างกัน การหมุนอุปกรณ์มักทําให้แอปรั่วออบเจ็กต์
Activity
,Context
หรือView
เนื่องจากระบบจะสร้างActivity
ขึ้นมาใหม่ และหากแอปของคุณเก็บข้อมูลอ้างอิงออบเจ็กต์ดังกล่าวไว้ที่อื่น ระบบจะเก็บขยะไม่ได้ - สลับไปมาระหว่างแอปของคุณกับแอปอื่นขณะอยู่ในสถานะกิจกรรมที่แตกต่างกัน เช่น ไปที่หน้าจอหลักแล้วกลับไปที่แอป
ส่งออกและนำเข้าการบันทึกฮีปดัมป์
คุณสามารถ
ส่งออกและนำเข้าฮีปดัมป์
จากแท็บการบันทึกที่ผ่านมาในเครื่องมือสร้างโปรไฟล์ Android Studio จะบันทึก
กำลังบันทึกเป็นไฟล์ .hprof
หรือจะใช้เครื่องมือวิเคราะห์ไฟล์ .hprof
อื่นก็ได้ เช่น
jhat
คุณต้องแปลงไฟล์ .hprof
จากรูปแบบ Android เป็น Java SE
รูปแบบไฟล์ .hprof
หากต้องการแปลงรูปแบบไฟล์ ให้ใช้hprof-conv
เครื่องมือ
ที่มีให้ในไดเรกทอรี {android_sdk}/platform-tools/
เรียกใช้ hprof-conv
ที่มีอาร์กิวเมนต์ 2 ตัว ได้แก่ ชื่อไฟล์ .hprof
เดิม และตำแหน่งที่จะ
เขียนไฟล์ .hprof
ที่แปลงแล้ว รวมถึงชื่อไฟล์ .hprof
ใหม่ เช่น
hprof-conv heap-original.hprof heap-converted.hprof