บันทึกฮีปดัมป์เพื่อดูว่าออบเจ็กต์ใดในแอปกำลังใช้หน่วยความจำมากเกินไปในขณะที่ บันทึก และระบุ หน่วยความจำรั่วไหล หรือลักษณะการทำงานของการจัดสรรหน่วยความจำ ที่ทำให้เกิดการกระตุก ค้าง และแม้แต่แอปขัดข้อง การบันทึกฮีปดัมป์หลังจากเซสชันของผู้ใช้ที่ยาวนานจะเป็นประโยชน์อย่างยิ่ง เนื่องจากอาจแสดงออบเจ็กต์ที่ยังอยู่ในหน่วยความจำซึ่งไม่ควรอยู่แล้ว
หน้านี้อธิบายเครื่องมือที่ Android Studio มีไว้เพื่อรวบรวมและวิเคราะห์ฮีปดัมป์ หรือคุณจะตรวจสอบหน่วยความจำของแอปจาก
บรรทัดคำสั่งด้วย dumpsys และยัง
ดูเหตุการณ์ระบบจัดการหน่วยความจำที่ไม่ใช้แล้ว (GC) ใน Logcat ได้อีกด้วย
เหตุผลที่ควรสร้างโปรไฟล์หน่วยความจำของแอป
Android มีสภาพแวดล้อมหน่วยความจำที่มีการจัดการเมื่อ Android กำหนดว่า แอปของคุณไม่ได้ใช้ออบเจ็กต์บางรายการอีกต่อไป ตัวเก็บขยะจะปล่อย หน่วยความจำที่ไม่ได้ใช้กลับไปยังฮีป Android ปรับปรุงวิธีค้นหาหน่วยความจำที่ไม่ได้ใช้อย่างต่อเนื่อง แต่ในบางจุดของ Android ทุกเวอร์ชัน ระบบจะต้องหยุดโค้ดของคุณชั่วคราว โดยส่วนใหญ่แล้ว การหยุดชั่วคราวจะสังเกตเห็นได้ยาก อย่างไรก็ตาม หากแอปจัดสรรหน่วยความจำเร็วกว่าที่ระบบจะรวบรวมได้ แอปของคุณอาจล่าช้าในขณะที่ตัวเก็บขยะปล่อยหน่วยความจำให้เพียงพอต่อการจัดสรรของคุณ ความล่าช้าอาจทำให้แอปข้ามเฟรมและทำให้เกิดความช้าที่มองเห็นได้
แม้ว่าแอปของคุณจะไม่ได้แสดงอาการช้า แต่หากหน่วยความจำรั่วไหล แอปก็อาจเก็บหน่วยความจำนั้นไว้แม้ว่าจะทำงานอยู่เบื้องหลังก็ตาม ลักษณะการทำงานนี้อาจทำให้ประสิทธิภาพหน่วยความจำของระบบส่วนอื่นๆ ช้าลงโดยบังคับให้เกิดเหตุการณ์ระบบจัดการหน่วยความจำที่ไม่ใช้แล้วที่ไม่จำเป็น ในที่สุด ระบบจะบังคับให้หยุดกระบวนการของแอปเพื่อเรียกคืนหน่วยความจำ จากนั้นเมื่อผู้ใช้กลับมาที่แอป กระบวนการของแอปจะต้องรีสตาร์ททั้งหมด
ดูข้อมูลเกี่ยวกับแนวทางปฏิบัติในการเขียนโปรแกรมที่ช่วยลดการใช้หน่วยความจำของแอปได้ที่ จัดการหน่วยความจำของแอป
ภาพรวมของฮีปดัมป์
หากต้องการบันทึกฮีปดัมป์ ให้เลือกงานวิเคราะห์การใช้หน่วยความจำ (ฮีปดัมป์) (ใช้ เครื่องมือสร้างโปรไฟล์: เรียกใช้ 'แอป' เป็นแบบแก้ไขข้อบกพร่องได้ (ข้อมูลที่สมบูรณ์)) เพื่อบันทึกฮีป ดัมป์ ขณะที่บันทึกฮีปดัมป์ ปริมาณหน่วยความจำ Java อาจเพิ่มขึ้นชั่วคราว ซึ่งเป็นเรื่องปกติเนื่องจากฮีปดัมป์เกิดขึ้นในกระบวนการเดียวกับแอปและต้องใช้หน่วยความจำบางส่วนเพื่อรวบรวมข้อมูล หลังจากบันทึกฮีปดัมป์แล้ว คุณจะเห็นข้อมูลต่อไปนี้
dumpHprofData()
รายการคลาสจะแสดงข้อมูลต่อไปนี้
- การจัดสรร: จำนวนการจัดสรรในฮีป
ขนาดเนทีฟ: ปริมาณหน่วยความจำเนทีฟทั้งหมดที่ใช้โดยออบเจ็กต์ประเภทนี้ (หน่วยเป็น ไบต์) คุณจะเห็นหน่วยความจำที่นี่สำหรับออบเจ็กต์บางรายการที่จัดสรรใน Java เนื่องจาก Android ใช้หน่วยความจำเนทีฟสำหรับคลาสเฟรมเวิร์กบางรายการ เช่น
Bitmapขนาดตื้น: ปริมาณหน่วยความจำ Java ทั้งหมดที่ใช้โดยออบเจ็กต์ประเภทนี้ (หน่วยเป็น ไบต์)
ขนาดที่คงไว้: ขนาดหน่วยความจำทั้งหมดที่คงไว้เนื่องจากอินสแตนซ์ทั้งหมดของคลาสนี้ (หน่วยเป็นไบต์)
ใช้เมนูฮีปเพื่อกรองไปยังฮีปบางรายการ
- ฮีปของแอป (ค่าเริ่มต้น): ฮีปหลักที่แอปจัดสรรหน่วยความจำ
- ฮีปรูปภาพ: อิมเมจบูตของระบบ ซึ่งมีคลาสที่โหลดไว้ล่วงหน้าในระหว่างเวลาบูต การจัดสรรที่นี่จะไม่ย้ายหรือหายไป
- ฮีป Zygote: ฮีปคัดลอกเมื่อเขียนที่กระบวนการของแอปแยกออกมาใน ระบบ Android
ใช้เมนูแบบเลื่อนลงการจัดเรียงเพื่อเลือกวิธีจัดเรียงการจัดสรร
- จัดเรียงตามคลาส (ค่าเริ่มต้น): จัดกลุ่มการจัดสรรทั้งหมดตามชื่อคลาส
- จัดเรียงตามแพ็กเกจ: จัดกลุ่มการจัดสรรทั้งหมดตามชื่อแพ็กเกจ
ใช้เมนูแบบเลื่อนลงคลาสเพื่อกรองไปยังกลุ่มคลาส
- คลาสทั้งหมด (ค่าเริ่มต้น): แสดงคลาสทั้งหมด รวมถึงคลาสจากไลบรารี และการขึ้นต่อกัน
- แสดงหน่วยความจำรั่วไหลของกิจกรรม/Fragment: แสดงคลาสที่ทำให้เกิดหน่วยความจำรั่วไหล
- แสดงคลาสโปรเจ็กต์: แสดงเฉพาะคลาสที่กำหนดโดยโปรเจ็กต์
คลิกชื่อคลาสเพื่อเปิดบานหน้าต่างอินสแตนซ์ อินสแตนซ์แต่ละรายการที่แสดงจะมีข้อมูลต่อไปนี้
- ความลึก: จำนวนฮอปที่สั้นที่สุดจากรูท GC ไปยังอินสแตนซ์ที่เลือก
- ขนาดเนทีฟ: ขนาดของอินสแตนซ์นี้ในหน่วยความจำเนทีฟ คอลัมน์นี้จะแสดงเฉพาะใน Android 7.0 ขึ้นไป
- ขนาดตื้น: ขนาดของอินสแตนซ์นี้ในหน่วยความจำ Java
- ขนาดที่เก็บไว้: ขนาดหน่วยความจำที่อินสแตนซ์นี้ครอบครอง (ตาม แผนผังผู้ครอบครอง))
คลิกอินสแตนซ์เพื่อแสดงรายละเอียดอินสแตนซ์ ซึ่งรวมถึงฟิลด์
และการอ้างอิง ประเภทฟิลด์และการอ้างอิงทั่วไปคือประเภทที่มีโครงสร้าง
,
อาร์เรย์
,
และประเภทข้อมูลดั้งเดิม
ใน Java คลิกขวาที่ฟิลด์หรือการอ้างอิงเพื่อไปยังอินสแตนซ์หรือบรรทัดที่เชื่อมโยงในโค้ดที่มา
- ฟิลด์: แสดงฟิลด์ทั้งหมดในอินสแตนซ์นี้
- การอ้างอิง: แสดงการอ้างอิงทั้งหมดไปยังออบเจ็กต์ที่ไฮไลต์ในแท็บ อินสแตนซ์
ค้นหาหน่วยความจำรั่วไหล
หากต้องการกรองไปยังคลาสที่อาจเชื่อมโยงกับหน่วยความจำรั่วไหลอย่างรวดเร็ว ให้เปิดเมนูแบบเลื่อนลงคลาสแล้วเลือกแสดงหน่วยความจำรั่วไหลของกิจกรรม/Fragment Android Studio
จะแสดงคลาสที่ระบบคิดว่าบ่งบอกถึงหน่วยความจำรั่วไหลสำหรับ
Activity และ
Fragment อินสแตนซ์ในแอป
หากต้องการค้นหาหน่วยความจำรั่วไหลด้วยตนเองมากขึ้น ให้เรียกดูรายการคลาสและอินสแตนซ์เพื่อค้นหาออบเจ็กต์ที่มีขนาดที่คงไว้ ใหญ่ มองหาหน่วยความจำรั่วไหลที่เกิดจากสาเหตุใดสาเหตุหนึ่งต่อไปนี้
- การอ้างอิง
ActivityหรือContextที่มีอายุการใช้งานยาวนานซึ่งอาจทำให้กราฟการจัดองค์ประกอบ Compose ที่โฮสต์รั่วไหล (เช่นComposeViewและคอมโพสได้ย่อย) - ออบเจ็กต์สถานะ Jetpack Compose (
MutableState) ตัวยึดสถานะ หรือแลมบ์ดาที่เก็บContextรั่วไหล - ลืมล้างข้อมูล Listener หรือ Observer ในบล็อก
onDisposeของDisposableEffect - คลาสภายในที่ไม่ใช่แบบคงที่ เช่น
Runnableซึ่งสามารถเก็บอินสแตนซ์Activityได้ - แคชที่เก็บออบเจ็กต์ไว้นานกว่าที่จำเป็น
เมื่อพบหน่วยความจำรั่วไหลที่อาจเกิดขึ้น ให้ใช้แท็บฟิลด์ และการอ้างอิง ในรายละเอียดอินสแตนซ์ เพื่อข้ามไปยังอินสแตนซ์หรือบรรทัดโค้ดที่มาที่ต้องการ
กระตุ้นให้เกิดหน่วยความจำรั่วไหลเพื่อทำการทดสอบ
หากต้องการวิเคราะห์การใช้งานหน่วยความจำ คุณควรทดสอบโค้ดแอปและพยายามบังคับให้เกิดหน่วยความจำรั่วไหล วิธีหนึ่งในการกระตุ้นให้เกิดหน่วยความจำรั่วไหลในแอปคือการปล่อยให้แอปทำงานสักพักก่อนที่จะตรวจสอบฮีป หน่วยความจำรั่วไหลอาจค่อยๆ ไหลขึ้นไปที่ด้านบนของการจัดสรรในฮีป อย่างไรก็ตาม ยิ่งหน่วยความจำรั่วไหลมีขนาดเล็กเท่าใด คุณก็ยิ่งต้องเรียกใช้แอปนานขึ้นเท่านั้นจึงจะเห็นหน่วยความจำรั่วไหล
นอกจากนี้ คุณยังกระตุ้นให้เกิดหน่วยความจำรั่วไหลได้ด้วยวิธีใดวิธีหนึ่งต่อไปนี้
- หมุนอุปกรณ์จากแนวตั้งเป็นแนวนอนและกลับไปกลับมาหลายครั้งขณะอยู่ในสถานะกิจกรรมต่างๆ การหมุนอุปกรณ์มักทำให้แอป
เกิดหน่วยความจำรั่วไหลของ
Activity(และด้วยเหตุนี้จึงทำให้แผนผัง UI ของ Compose ที่โฮสต์และ แผนผังสถานะที่เชื่อมโยงเกิดหน่วยความจำรั่วไหล) หากแอปมีการอ้างอิงActivityหรือContextภายในตัวยึดสถานะหรือการดำเนินการแบบอะซิงโครนัส - สลับไปมาระหว่างแอปของคุณกับแอปอื่นขณะอยู่ในสถานะกิจกรรมต่างๆ เช่น ไปที่หน้าจอหลัก แล้วกลับมาที่แอป
ส่งออกและนำเข้าการบันทึกฮีปดัมป์
คุณสามารถ
ส่งออกและนำเข้าไฟล์ฮีปดัมป์
จากแท็บการบันทึกที่ผ่านมาในโปรไฟล์ได้ Android Studio จะบันทึกการบันทึกเป็นไฟล์ .hprof
หรือหากต้องการใช้เครื่องมือวิเคราะห์ไฟล์ .hprof อื่น เช่น
jhat,
คุณต้องแปลงไฟล์ .hprof จากรูปแบบ Android เป็นรูปแบบไฟล์ .hprof ของ Java SE หากต้องการแปลงรูปแบบไฟล์ ให้ใช้เครื่องมือ hprof-conv ที่มีให้ในไดเรกทอรี {android_sdk}/platform-tools/ เรียกใช้คำสั่ง hprof-conv โดยมีอาร์กิวเมนต์ 2 รายการ ได้แก่ ชื่อไฟล์ .hprof เดิมและตำแหน่งที่จะเขียนไฟล์ .hprof ที่แปลงแล้ว ซึ่งรวมถึงชื่อไฟล์ .hprof ใหม่ ตัวอย่างเช่น
hprof-conv heap-original.hprof heap-converted.hprof