บันทึกฮีปดัมป์เพื่อดูว่าออบเจ็กต์ใดในแอปใช้หน่วยความจำมากที่สุดในขณะที่ บันทึก และระบุ หน่วยความจำรั่วไหล หรือลักษณะการทำงานของการจัดสรรหน่วยความจำ ที่ทำให้เกิดการกระตุก ค้าง และแม้แต่แอปขัดข้อง การบันทึกฮีปดัมป์หลังจากเซสชันของผู้ใช้ที่ยาวนานจะเป็นประโยชน์อย่างยิ่ง เนื่องจากอาจแสดงออบเจ็กต์ที่ยังอยู่ในหน่วยความจำซึ่งไม่ควรอยู่แล้ว
หน้านี้อธิบายเครื่องมือที่ Android Studio มีไว้เพื่อรวบรวมและวิเคราะห์ฮีปดัมป์ หรือคุณจะตรวจสอบหน่วยความจำของแอปจาก
บรรทัดคำสั่งด้วย dumpsys และยัง
ดูเหตุการณ์ระบบจัดการหน่วยความจำที่ไม่ใช้แล้ว (GC) ใน Logcat ได้อีกด้วย
เหตุผลที่ควรสร้างโปรไฟล์หน่วยความจำของแอป
Android มีสภาพแวดล้อมหน่วยความจำที่มีการจัดการเมื่อ Android กำหนดว่า แอปของคุณไม่ได้ใช้ออบเจ็กต์บางรายการอีกต่อไป ตัวเก็บขยะจะปล่อย หน่วยความจำที่ไม่ได้ใช้กลับไปยังฮีป Android ปรับปรุงวิธีค้นหาหน่วยความจำที่ไม่ได้ใช้อยู่เสมอ แต่ในบางจุดใน Android ทุกเวอร์ชัน ระบบจะต้องหยุดโค้ดของคุณชั่วคราว โดยส่วนใหญ่แล้วการหยุดชั่วคราวจะสังเกตเห็นได้ยาก อย่างไรก็ตาม หากแอปจัดสรรหน่วยความจำเร็วกว่าที่ระบบจะรวบรวมได้ แอปของคุณอาจล่าช้าในขณะที่ตัวเก็บขยะปล่อยหน่วยความจำให้เพียงพอต่อการจัดสรรของคุณ ความล่าช้าอาจทำให้แอปข้ามเฟรมและทำให้เกิดความช้าที่สังเกตเห็นได้
แม้ว่าแอปของคุณจะไม่ได้แสดงอาการช้า แต่หากหน่วยความจำรั่วไหล แอปก็อาจเก็บหน่วยความจำนั้นไว้แม้ว่าจะอยู่ในเบื้องหลังก็ตาม ลักษณะการทำงานนี้อาจทำให้ประสิทธิภาพหน่วยความจำของระบบส่วนอื่นๆ ช้าลงโดยบังคับให้เกิดเหตุการณ์ระบบจัดการหน่วยความจำที่ไม่ใช้แล้วที่ไม่จำเป็น ในที่สุดระบบจะบังคับให้หยุดกระบวนการของแอปเพื่อเรียกคืนหน่วยความจำ จากนั้นเมื่อผู้ใช้กลับมาที่แอป กระบวนการของแอปจะต้องรีสตาร์ททั้งหมด
ดูข้อมูลเกี่ยวกับแนวทางปฏิบัติในการเขียนโปรแกรมที่ช่วยลดการใช้หน่วยความจำของแอปได้ที่ จัดการหน่วยความจำของแอป
ภาพรวมของฮีปดัมป์
หากต้องการบันทึกฮีปดัมป์ ให้เลือกงาน วิเคราะห์การใช้หน่วยความจำ (ฮีปดัมป์) (ใช้ เครื่องมือสร้างโปรไฟล์: เรียกใช้ 'แอป' เป็นแบบแก้ไขข้อบกพร่องได้ (ข้อมูลที่สมบูรณ์)) เพื่อบันทึกฮีป ดัมป์ ขณะที่ดัมป์ฮีป ปริมาณหน่วยความจำ Java อาจเพิ่มขึ้นชั่วคราว ซึ่งเป็นเรื่องปกติเนื่องจากฮีปดัมป์เกิดขึ้นในกระบวนการเดียวกับแอปของคุณและต้องใช้หน่วยความจำบางส่วนเพื่อรวบรวมข้อมูล หลังจากบันทึกฮีปดัมป์แล้ว คุณจะเห็นข้อมูลต่อไปนี้
รายการคลาสจะแสดงข้อมูลต่อไปนี้
- การจัดสรร: จำนวนการจัดสรรในฮีป
ขนาดเนทีฟ: ปริมาณหน่วยความจำเนทีฟทั้งหมดที่ใช้โดยออบเจ็กต์ประเภทนี้ (หน่วยเป็น ไบต์) คุณจะเห็นหน่วยความจำที่นี่สำหรับออบเจ็กต์บางรายการที่จัดสรรใน Java เนื่องจาก Android ใช้หน่วยความจำเนทีฟสำหรับคลาสเฟรมเวิร์กบางคลาส เช่น
Bitmapขนาดตื้น: ปริมาณหน่วยความจำ Java ทั้งหมดที่ใช้โดยออบเจ็กต์ประเภทนี้ (หน่วยเป็น ไบต์)
ขนาดที่คงไว้: ขนาดหน่วยความจำทั้งหมดที่คงไว้เนื่องจากอินสแตนซ์ทั้งหมดของคลาสนี้ (หน่วยเป็นไบต์)
ใช้เมนูฮีปเพื่อกรองฮีปบางรายการ
- ฮีปของแอป (ค่าเริ่มต้น): ฮีปหลักที่แอปของคุณจัดสรรหน่วยความจำ
- ฮีปรูปภาพ: อิมเมจบูตของระบบ ซึ่งมีคลาสที่โหลดไว้ล่วงหน้าในระหว่างการบูต การจัดสรรที่นี่จะไม่ย้ายหรือหายไป
- ฮีป Zygote: ฮีปคัดลอกเมื่อเขียนที่กระบวนการของแอปแยกออกมาใน ระบบ Android
ใช้เมนูแบบเลื่อนลงการจัดเรียงเพื่อเลือกวิธีจัดเรียงการจัดสรร
- จัดเรียงตามคลาส (ค่าเริ่มต้น): จัดกลุ่มการจัดสรรทั้งหมดตามชื่อคลาส
- จัดเรียงตามแพ็กเกจ: จัดกลุ่มการจัดสรรทั้งหมดตามชื่อแพ็กเกจ
ใช้เมนูแบบเลื่อนลงคลาสเพื่อกรองกลุ่มคลาส
- คลาสทั้งหมด (ค่าเริ่มต้น): แสดงคลาสทั้งหมด รวมถึงคลาสจากไลบรารี และการขึ้นต่อกัน
- แสดงหน่วยความจำรั่วไหลของกิจกรรม/เฟร็กเมนต์: แสดงคลาสที่ทำให้เกิดหน่วยความจำรั่วไหล
- แสดงคลาสโปรเจ็กต์: แสดงเฉพาะคลาสที่กำหนดโดยโปรเจ็กต์ของคุณ
คลิกชื่อคลาสเพื่อเปิดบานหน้าต่างอินสแตนซ์ อินสแตนซ์แต่ละรายการที่แสดงจะมีข้อมูลต่อไปนี้
- ความลึก: จำนวนฮอปที่สั้นที่สุดจากรูท GC ไปยังอินสแตนซ์ที่เลือก
- ขนาดเนทีฟ: ขนาดของอินสแตนซ์นี้ในหน่วยความจำเนทีฟ คอลัมน์นี้จะแสดงเฉพาะใน Android 7.0 ขึ้นไป
- ขนาดตื้น: ขนาดของอินสแตนซ์นี้ในหน่วยความจำ Java
- ขนาดที่เก็บไว้: ขนาดหน่วยความจำที่อินสแตนซ์นี้ครอบครอง (ตาม แผนผังผู้ครอบครอง))
คลิกอินสแตนซ์เพื่อแสดงรายละเอียดอินสแตนซ์ ซึ่งรวมถึงฟิลด์
และการอ้างอิง ประเภทฟิลด์และการอ้างอิงทั่วไปคือประเภทที่มีโครงสร้าง
,
อาร์เรย์
,
และประเภทข้อมูลดั้งเดิม
ใน Java คลิกขวาที่ฟิลด์หรือการอ้างอิงเพื่อไปยังอินสแตนซ์หรือบรรทัดที่เกี่ยวข้องในซอร์สโค้ด
- ฟิลด์: แสดงฟิลด์ทั้งหมดในอินสแตนซ์นี้
- การอ้างอิง: แสดงการอ้างอิงทั้งหมดไปยังออบเจ็กต์ที่ไฮไลต์ในแท็บ อินสแตนซ์
ค้นหาหน่วยความจำรั่วไหล
หากต้องการกรองคลาสที่อาจเกี่ยวข้องกับหน่วยความจำรั่วไหลอย่างรวดเร็ว ให้เปิดเมนูแบบเลื่อนลงคลาสแล้วเลือกแสดงหน่วยความจำรั่วไหลของกิจกรรม/แฟรกเมนต์ 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