رونوشت پشته را ضبط کنید تا ببینید کدام اشیاء در برنامهتان در زمان ضبط از حافظه استفاده میکنند و نشتهای حافظه یا رفتار تخصیص حافظه را که منجر به لکنت، توقف، و حتی ازکارافتادن برنامه میشود شناسایی کنید. بهویژه مفید است که رونوشت پشته را پساز یک جلسه کاربری طولانی بگیرید، زیرا میتواند اشیایی را که هنوز در حافظه هستند و نباید دیگر آنجا باشند نشان دهد.
این صفحه ابزاری را که «استودیو Android» برای جمعآوری و تجزیهوتحلیل رونوشتهای پشته ارائه میدهد شرح میدهد. یا میتوانید حافظه برنامهتان را از خط فرمان با dumpsys بازرسی کنید و همچنین
رویدادهای جمعآوری زباله (GC) را در Logcat ببینید.
چرا باید حافظه برنامهتان را نمایه کنید
Android محیط حافظه مدیریتشده ارائه میدهد—وقتی Android تشخیص دهد که برنامه شما دیگر از برخی اشیا استفاده نمیکند، جمعآورنده زباله حافظه استفادهنشده را به توده برمیگرداند. نحوه پیدا کردن حافظه استفادهنشده توسط Android بهطور مداوم درحال بهبود است، اما در برخیاز نسخههای Android، سیستم باید برای مدت کوتاهی کد شما را موقتاً متوقف کند. در بیشتر مواقع، این مکثها نامحسوس هستند. بااینحال، اگر برنامه شما حافظه را سریعتر از آنچه سیستم میتواند جمعآوری کند اختصاص دهد، ممکن است برنامه شما بهتأخیر بیفتد تا زمانی که جمعآورنده حافظه کافی را برای برآورده کردن اختصاصهای شما آزاد کند. این تأخیر میتواند باعث شود برنامهتان قابها را رد کند و کندی قابلمشاهدهای ایجاد کند.
حتی اگر برنامهتان کندی نشان ندهد، اگر نشت حافظه داشته باشد، میتواند آن حافظه را حتی زمانی که در پسزمینه است حفظ کند. این رفتار میتواند با اجبار به رویدادهای غیرضروری جمعآوری زباله، عملکرد بقیه حافظه سیستم را کند کند. درنهایت، سیستم مجبور میشود فرایند برنامه شما را متوقف کند تا حافظه را بازیابی کند. سپس وقتی کاربر به برنامه شما برمیگردد، فرایند برنامه باید کاملاً بازراهاندازی شود.
برای کسب اطلاعات درباره روشهای برنامهنویسی که میتواند مصرف حافظه برنامهتان را کاهش دهد، [مدیریت حافظه برنامه]حافظه را بخوانید.
نمای کلی رونوشت پشته
برای ضبط رونوشت پشته، تکلیف تحلیل استفاده از حافظه (رونوشت پشته) را انتخاب کنید (از نمایهساز: اجرای «برنامه» بهعنوان قابلاشکالزدایی (دادههای کامل) استفاده کنید) تا رونوشت پشته ضبط شود. هنگام تخلیه توده، ممکن است مقدار حافظه Java موقتاً افزایش یابد. این امر طبیعی است زیرا رونوشت پشته در همان فرایند برنامه شما رخ میدهد و برای جمعآوری دادهها به مقداری حافظه نیاز دارد. پساز ضبط رونوشت پشته، موارد زیر را میبینید:
فهرست کلاسها اطلاعات زیر را نشان میدهد:
- تخصیصها: تعداد تخصیصها در پشته.
اندازه بومی: مقدار کل حافظه بومی استفادهشده توسط این نوع شیء (به بایت). در اینجا حافظه را برای برخیاز اشیای اختصاصدادهشده در Java خواهید دید زیرا Android از حافظه بومی برای برخیاز کلاسهای چارچوب، مثل
Bitmap، استفاده میکند.اندازه سطحی: مقدار کل حافظه Java که این نوع شیء استفاده میکند (به بایت).
فضای حفظشده: اندازه کل حافظهای که بهدلیل همه نمونههای این کلاس حفظ شده است (به بایت).
از منو توده برای فیلتر کردن تودههای خاص استفاده کنید:
- توده برنامه (پیشفرض): توده اصلی که برنامهتان در آن حافظه اختصاص میدهد.
- توده تصویر: تصویر راهاندازی سیستم، حاوی کلاسهایی که درطول زمان راهاندازی ازپیش بارگیری شدهاند. تخصیصها در اینجا هرگز جابهجا نمیشوند یا ازبین نمیروند.
- انبوهه Zygote: انبوهه کپی-در-نوشتن که فرایند برنامه از آن در سیستم Android منشعب میشود.
از منوی کرکرهای ترتیب استفاده کنید تا نحوه ترتیببندی تخصیصها را انتخاب کنید:
- مرتبسازی براساس کلاس (پیشفرض): همه تخصیصها را براساس نام کلاس گروهبندی میکند.
- مرتبسازی براساس بسته: همه تخصیصها را براساس نام بسته گروهبندی میکند.
از منوی کرکرهای کلاس برای فیلتر کردن گروههای کلاس استفاده کنید:
- همه کلاسها (پیشفرض): همه کلاسها را نشان میدهد، ازجمله کلاسهای کتابخانهها و وابستگیها.
- نمایش نشتهای فعالیت/تکه: کلاسهایی را که باعث نشت حافظه میشوند نشان میدهد.
- نمایش کلاسهای پروژه: فقط کلاسهای تعریفشده توسط پروژه شما را نشان میدهد.
روی نام کلاس کلیک کنید تا قاب نمونه باز شود. هر نمونه فهرستشده شامل موارد زیر است:
- عمق: کوتاهترین تعداد پرش از هر ریشه GC به نمونه انتخابشده.
- اندازه بومی: اندازه این نمونه در حافظه بومی. این ستون فقط برای Android نسخه ۷.۰ و بالاتر نمایان است.
- اندازه سطحی: اندازه این نمونه در حافظه Java.
- فضای حفظشده: اندازه حافظهای که این نمونه بر آن تسلط دارد (طبق درخت تسلط).
روی یک نمونه کلیک کنید تا جزئیات نمونه، ازجمله فیلدها و مراجع آن نمایش داده شود. انواع فیلد و مرجع رایج عبارتاند از انواع ساختاریافته
،
آرایهها
،
و انواع دادههای اولیه
در Java. روی فیلد یا مرجعی کلیک راست کنید تا به نمونه یا خط مرتبط در کد منبع بروید.
- فیلدها: همه فیلدهای این نمونه را نشان میدهد.
- مرجعها: همه مرجعهای شیء برجستهشده در برگه نمونه را نشان میدهد.
شناسایی کردن نگاشتهای بیتی تکراری
همچنین میتوانید نقشههای بیتی زائد را در نمای «رونوشت پشته» که با Android Studio Narwhal 4 شروع میشود شناسایی کنید.
در اینجا نحوه شکار آنها آمده است:
- باز کردن برگه «نمایهساز» در «استودیو Android»
- روی رونوشت پشته (یا تحلیل استفاده از حافظه) کلیک کنید و روی «ضبط» کلیک کنید تا عکس آنی از وضعیت فعلی حافظه برنامهتان گرفته شود.
- نتایج تحلیل را برای پیدا کردن مثلث هشدار زرد ⚠️ اسکن کنید.
«استودیو Android» از این علامت برای نشانگذاری بیتمپهای تکراری که چند بار ذخیره شدهاند استفاده میکند.
- یا به سرصفحه نمایهساز بروید، فیلتر کردن براساس: را انتخاب کنید، و تنظیم نقشههای بیتی تکراری را انتخاب کنید.
- روی هر ورودی پرچمگذاریشده کلیک کنید تا قاب پیشنمایش نگاشت بیتی باز شود، که به شما امکان میدهد دقیقاً ببینید کدام تصویر تکرارکننده تخلف است.
- از آن تأیید بصری برای ردیابی منطق بارگیری زائد در کد خود استفاده کنید و یک استراتژی ذخیرهسازی بهتر را پیادهسازی کنید.
یافتن نشت حافظه
برای فیلتر کردن سریع کلاسهایی که ممکن است با نشت حافظه مرتبط باشند،
منوی کرکرهای کلاس را باز کنید و نمایش نشتهای فعالیت/تکه را انتخاب کنید. Android Studio
کلاسهایی را نشان میدهد که فکر میکند نشاندهنده نشت حافظه برای
نمونههای Activity و
Fragment در برنامهتان است.
برای جستجوی دستیتر نشت حافظه، فهرستهای کلاس و نمونه را مرور کنید تا اشیاء با فضای حفظشده بزرگ را پیدا کنید. بهدنبال نشت حافظه ناشی از هریک از موارد زیر باشید:
- ارجاعهای طولانیمدت به
ActivityیاContextکه میتواند نمودار ترکیببندی Compose میزبانیشده را لو دهد (مانندComposeViewو ترکیبشدنیهای فرعی آن). - نشت کردن اشیای حالت Jetpack Compose (
MutableState)، نگهدارندههای حالت، یا لامبداهایی کهContextرا ضبط میکنند. - فراموش کردن پاک کردن شنوندگان یا ناظران در بلوک
onDisposeDisposableEffect. - کلاسهای داخلی غیرایستا، مانند
Runnable، که میتوانند یک نمونهActivityرا نگه دارند. - حافظههای پنهانی که اشیا را بیشتر از حد لازم نگه میدارند.
وقتی نشتهای احتمالی حافظه را پیدا کردید، از برگههای فیلدها و ارجاعها در جزئیات نمونه استفاده کنید تا به نمونه یا خط کد منبع موردنظر بروید.
راهاندازی نشت حافظه برای آزمایش
برای تجزیهوتحلیل استفاده از حافظه، باید کد برنامهتان را تحت فشار قرار دهید و سعی کنید نشت حافظه را بهزور ایجاد کنید. یکی از راههای تحریک نشت حافظه در برنامه این است که اجازه دهید مدتی اجرا شود و سپس پشته را بررسی کنید. نشتها ممکن است به بالای تخصیصها در توده نفوذ کنند. بااینحال، هرچه نشت کوچکتر باشد، باید برنامه را برای مدت طولانیتری اجرا کنید تا بتوانید آن را ببینید.
همچنین میتوانید نشت حافظه را به یکی از روشهای زیر راهاندازی کنید:
- دستگاه را چندبار از حالت عمودی به افقی و برعکس بچرخانید
درحالیکه در حالتهای فعالیت مختلف قرار دارد. چرخاندن دستگاه اغلب میتواند باعث شود برنامه
Activity(و درنتیجه درخت میانای کاربری Compose میزبانیشده و درختهای حالت مرتبط) را نشت دهد اگر برنامه شما ارجاعی بهActivityیاContextدر عملیاتهای ناهمگام یا نگهدارندههای حالت داشته باشد. - درحالیکه در حالتهای فعالیت مختلف هستید، بین برنامه خود و برنامه دیگری جابهجا شوید. برای مثال، به صفحه اصلی بروید، سپس به برنامهتان برگردید.
صادر و وارد کردن ضبط رونوشت پشته
میتوانید
فایل رونوشت پشته را از زبانه ضبطهای گذشته در نمایهساز
صادر و وارد کنید. «استودیو Android» قطعه ضبطشده را بهصورت فایل .hprof ذخیره میکند.
یا برای استفاده از تحلیلگر فایل .hprof دیگری مثل
jhat،
باید فایل .hprof را از قالب Android به قالب فایل Java SE
.hprof تبدیل کنید. برای تبدیل قالب فایل، از ابزار hprof-conv
ارائهشده در فهرست راهنمای {android_sdk}/platform-tools/ استفاده کنید. فرمان hprof-conv را با دو آرگومان اجرا کنید: نام فایل اصلی .hprof و مکانی که فایل تبدیلشده .hprof در آن نوشته میشود، ازجمله نام فایل جدید .hprof. برای
مثال:
hprof-conv heap-original.hprof heap-converted.hprof