TimTim

سایت خبر خوان

هر آنچه که باید در مورد سرریز شدن حافظه در اپلیکیشن اندرویدی بدانید : 1

پنج شنبه 9 اسفند 97 | 16:37 - virgool.io - 25
سرریز حافظه در اندروید چیست؟ چگونه ایجاد می‌شود؟ و اینکه چگونه می‌توان...

ساخت یک اپ اندرویدی ساده هست، ولی ایجاد یک برنامه‌ای که هم کیفیتش بالا باشه و هم به لحاظ حافظه کارآمد باشه، کار ساده‌ای نیست. قبلا توی برنامه نویسی اندروید سعی میکردم فقط روی فیچرهایی که به چشم میان کار کنم و نه روی فیچرهایی که توی نگاه اول به چشم نمیان ( که البته بعدا فهمیدم کار اشتباهی انجام میدادم ). بهینه سازی برنامه از جمله، برطرف کردن سرریزهای حافظه هیچ وقت برام مهم نبود.

این مسئله‌ای که خدمتتون گفتم، همیشه باعث میشد که کیفیت و عملکرد برنامه‌ها در طولانی مدت به شدت کم بشه. به خاطر همین تصمیم گرفتم تا روی عملکرد برنامه بیشتر تمرکز کنم.

درسته که مفهوم سرریز حافظه برای خیلی از توسعه‌دهنده‌ها کمی دلهره‌آوره و پیدا کردن سرریز حافظه رو سخت و طاقت‌فرسا میدونن. ولی در حقیقت اینجوری نیست، بلکه وقتی خودتون شروع به پیدا کردنش کنید حتما خواهید فهمید که این کار خیلی هم لذت بخشه :) .

چرا جاوا از سرریزهای حافظه پیشگیری نمیکنه؟

توی برنامه‌نویسی اندروید شما به ندرت از زبانهایی مثل C و C++ - که توی اونها خودتون باید حافظه رو مدیریت کنید - استفاده میکنید. جاوا یک زبان خیلی خوب برای توسعه‌ی اندروید هست و باید اینو بگم که خوشبختانه جاوا خودش میتونه عمل clean up رو خیلی خوب انجام بده.

اولین باری که در مورد سرریز حافظه در اندروید خوندم، برام عجیب بود، چطور میشه که باید نگران سرریز شدن باشم، در حالی که جاوا خودش کار مدیریت حافظه رو انجام میده. عایا این به خاطر وجود مشکلی در آشغال جمع کن جاوا هست؟

نه قطعا اینطور نیست. سیستم آشغال جمع کن یا GC یکی از بهترین ویژگی‌های جاوا هست. کارشو اونجور که باید انجام میده و به این لحاظ مشکلی نداره، بنابراین به خاطر نوع برنامه نویسی ما هست که بعضی وقتا سیستم GC نمیتونه اونجور که باید، قطعه‌هایی از حافظه که رو که بلااستفاده شدن رو آزاد کنه.

یک نگاه اجمالی به این که سیستم GC توی جاوا چجوری کار میکنه؟

قبل از اینکه جلوتر بریم، لازمه قبلش در مورد اینکه آشغال جمع کن چجوری کار میکنه یکم اطلاعاتی داشته باشیم. مفهوم آشغال جمع کن خیلی ساده هست ولی گاهی اوقات در باطن امر خیلی پیچیده میشه.

یک دیاگرام برای درخت حافظه
یک دیاگرام برای درخت حافظه

هر اپلیکیشن اندرویدی یک نقطه‌ی شروع داره که اونجا آبجکتها ساخته میشن و متدها فراخوانی میشن. میتونیم این نقطه‌ی شروع رو معادل با ریشه‌ی درختمون در نظر بگیریم. بعضی از آبجکتها ارتباط مستقیمی با ریشه‌ی درخت دارن، و بعضیاشون هم رابطشون غیرمستقیمه.

بنابراین، یک زنجیره‌ای از ارتباطات رو داریم که یک درخت حافظه رو تشکیل میده. بنابراین، آشغال جمع‌کن از ریشه‌های GC شروع میشه و آبجکتهایی رو که به صورت مستقیم یا غیرمستقیم با ریشه ارتباط دارن رو ملاقات میکنه. در پایان این پروسه، بعضی از آبجکتها هرگز توسط GC ملاقات نمیشن.

این آبجکت‌هایی که گفتم آخرش آشغال‌های ما میشن و توسط آشغال جمع‌کن، از بین میرن.

خب، حالا سرریز حافظه چیه؟ و وقتی این مساله برام پیش اومد، باید چکار کنم؟

تعریف شسته رفته‌ی سرریز حافظه اینه که وقتی یک آبجکت بیش‌تر از حد مورد نیاز توی حافظه بمونه.

هر آبجکتی که طول عمرش تموم بشه و دیگه بهش نیاز نداشته باشیم،‌ باید خدافظی کنه و حافظه رو ترک کنه :). اما نه، ممکنه بعضی از وقتا شرایطی پیش بیاد که ارتباط یک آبجکت دیگه با این آبجکتی که میخوایم حذفش کنیم حفظ میشه و در این صورته که ما نمی‌تونیم آبجکت مورد نظر رو از حافظه جمعش کنیم. که همونجور که متوجه شدید به این شرایط میگن سرریز حافظه.

البته همیشه نباید نگران هر سرریز حافظه‌ای که توی برنامه اتفاق میفته بود. همه‌ی سرریزها پتانسیل خراب کردن برنامه رو ندارن.

بعضی از سرریزها ناچیز هستن ( مثلا در حد کیلوبایت ) که نیاز نیست نگرانش باشید چون خود فریمورک اندروید براتون مشکل رو برطرف میکنه. اینجور سرریزها حداقل اثر ممکن رو روی عملکرد برنامه میگذارن بنابراین میشه از اثرات اونا چشم پوشی کرد.

ولی نه، گاهی اوقات بعضی از سرریزها باعث ایجاد کرش برنامه یا لگ میشن. در این صورت لازمه که به صورت جدی مراقب اونا بود و اونا رو برطرف کرد.

موقع یک سرریز ناجور چه اتفاقی میفته؟

موقعی که از اپ استفاده میشه و حافظه ی هیپ شروع به پرشدن میکنه، یک آشغال جمع‌کن شروع به کار میکنه و آبجکتهای مرده رو جمع میکنه. این آشغال جمع کن‌ها به صورت غیرهمروند کار میکنن ( یعنی توی یک ترد دیگه ) و چندان سرعت اپ شما رو پایین نمیارن ( توقف 2 تا 5 میلی ثانیه‌ای برنامه ) ، ولی دقت کنید که، هرجی آشغال جمع کن کمتری اجرا بشه، عملکرد برنامتون بهتر خواهد شد.

درحقیقت وقتی که سرریز بدی توی برنامتون اتفاق میفته، آشغال جمع‌کن‌ها نمیتونن که حافظه رو اصلاح کنن که در نتیجه باعث میشه تا یک آشغال جمع‌کن بزرگتری شروع به کار کنه. اسم این آشغال جمع‌کن بزرگه هست : "stop-the-world". که باعث میشه به مدت 50 تا 10 میلی ثانیه ترد اصلی برنامه متوقف بشه. توی این موقعیت،‌ اپ شما دچار لگ میشه و تقریبا میشه گفت از کنترل خارج میشه.

اگه که این مشکل حل نشه، حافظه‌ی هیپ برنامه‌ی شما به صورت مداوم افزایش پیدا میکنه و در نتیجه باعث ایجاد مشکل outOfMemoryError میشه که نتیجش کرش شدن اپ شماست.

وقتی اثرات سرریز حافظه بر اپتون رو بدونید، راهکارش رو هم میتونید راحت پیدا کنید.

شناسایی سرریزهای حافظه

حالا که مطالبی رو در مورد برطرف کردن سرریزهای پنهان شده در حافظه یاد گرفتید، بعدش چجوری میخواید برطرفشون کنید؟

خبر خوبی که میتونم بهتون بدم اینه که اندروید استودیو یک ابزار قدرتمند و مفیدی برای این کار داره.

وقتی که دارید اپتون رو دیباگ میکنید، یه نگاهی هم به این سیستم مانیتورینگ حافظه بندازید. اولین نشانه‌ی سرریز حافظه اینه که وقتی دارین از برنامه استفاده میکنید - حتی اگه در پس زمینه هم باشه - این نمودار به طور مداوم هی رشد میکنه و پایین هم نمیاد.

میتونید از Allocation Tracker استفاده کنید تا ببینید که توی برنامتون به چیزهای مختلف چقد حافظه اختصاص داده شده. این میتونه به شما یک سرنخی بده تا متوجه بشید که چه چیزی حافظتون رو پر کرده و اینکه چجوری میشه برطرفش کرد.

ولی بازم این قضیه که گفتیم به تنهایی کافی نیست. علاوه بر این لازمه تا از آپشن Dump Java Heap استفاده کنید تا یک heap dump رو ایجاد کنه، که با استفاده از اون بتونیم یک اسنپشات از حافظه رو در لحظه‌ی سرریز بدست بیاریم. اینطور که به نظر میاد خیلی کار خسته‌کننده و پرزحمتیه؟ درسته، قبول دارم :)

خب حتما شما هم مثل من حال و حوصله‌ی انجام این کارها رو ندارین :) خب عیبی نداره میتونید از LeakCanary استفاده کنید. وقتی که این کتابخونه رو روی برنامتون اجرا میکنید هر وقت که لازم بشه، عمل memory dump رو انجام میده و دنبال سرریزهای حافظه میگرده، بعدش به شما یک نوتیفیکیشن میده و علت سرریز رو مشخص میکنه. LeakCanary تنها یکی از ابزارهای شناسایی سرریز حافظه هست و ابزارهای زیاد دیگه‌ای وجود دارن.

توی قسمت بعدی در مورد علتهای معمول سرریز و اینکه چجوری میشه اونا رو برطرف کرد خواهیم نوشت.

موبایل لَبْ, برنامه نویسی,برنامه نویسی اندروید,سرریز حافظه اندروید,آموزش برنامه نویسی,حافظه اندروید,