Skip to main content

مدیریت حافظه و garbage collection (جمع آور زباله) در جاوا

Memory management and garbage collection

در ویدئوی آموزشی حاضر ویژگی مدیریت اتوماتیک حافظه بررسی شده و در ادامه به زمان اجرای منقضی شدن ارجاعات پرداخته شده است. همچنین به ویژگی garbage collection یا جمع آوری زباله اشاره شده است و راهکارهایی برای مدیریت و تنظیم حافظه در دسترس ارائه گردیده است.

لینک کمکی ( official link ) – مدیریت حافظه و garbage collection (جمع آور زباله) (آموزش جامع جاوا Java) درس 7

مدیریت اتوماتیک حافظه در جاوا

با اینکه جاوا یک زبان از نوع کامپایل شده و استاتیک هستش، ولی برخلاف زبان هایی مثل سی و سی پلاس پلاس یا پاسکال؛ حافظه رو برای شما مدیریت میکنه، و نیازی نیست هر موقع که یک شیء ایجاد می کنید به طور صریح و غیر صریح حافظه ای به اون شیء اختصاص بدید و یا حافظه رو از اون شیء آزاد کنید. Garbage Collector یا جمع آوری آشغال یک ویژگی اصلی از ماشین مجازی جاوا هستش، که امکانات زیادی در اختیار ما میذاره. حالا میخوام در این ساعت از طهاکو دات آی آر توضیح بدم که این Garbage Collector چطوری کار می کنه، تا به عنوان یک برنامه نویس باهاش آشنا بشید و ببینید چه کاربردی داره. و نهایتاً توجهاتی که Garbage Collector نیاز داره رو بِسمتش معطوف کنید.
در واقع برنامه نویس از Garbage Collector استفاده نمی کنه بلکه از کارهای Garbage Collector منفعت زیادی میبره. در زبان های سی و سی پلاس پلاس که قابلیت Garbage Collector رو ندارن، برنامه نویس باید هر بار که یک شئ می سازه (با دستور new یا malloc) حتما باید پس از استفاده، اونها رو free کنه؛ که این کار برای برنامه نویس کاری زمانبر هست و از همه مهمتر اگه یادش بره free کنه برنامه به مرور حافظه زیادی اشغال می کنه و در کار برنامه اخلال ایجاد میشه. اما در زبان های برنامه نویسی که قابلیت Garbage Collector رو دارن، مانند جاوا و سی شارپ دیگه نیازی به free کردن مموری نیست و برنامه نویس می تونه تمرکزش رو بر روی کد نویسی بگذاره. محیط های زمان اجرای این زبان ها مانند JVM وظیفه free کردن memory رو با استفاده از الگوریتم های مختلف Garbage Collection بر عهده گرفته اند.
وقتی شما یک متغیر ایجاد می کنید که به یک شی پیچیده ارجاع داده میشه،
 اون متغیر در سریعترین حافظه ی در دسترس ذخیره میشه ولی اون شیء ای که بهش ارجاع داده شده، در حافظه ی heap ذخیره میشه.
در حقیقت دو نوع از حافظه وجود داره حافظه ی استک و حافظه ی هیپ. حافظه ی استک فضایی هست که دسترسی بهش  تا حدی سریع تر هست، و هیپ کمی کندتر هستش. ولی هیپ خاصیت پویاییش بیشتر هست. وقتی متغیرهای اولیه رو ایجاد می کنید، بسته به محتواشون ممکن هست در هیپ یا استک ذخیره بشن. ولی اشیاء پیچیده همیشه در هیپ ذخیره می شوند.
و هر زمان که هر متغیری در مموری به یک شیء ارجاع داده بشه،
اون شیء رو ذخیره میکنه و این نوع حافظه مشمول garbage collection نمیشه. پس اگه یک متغیر ایجاد کنید و اون به یک رشته، یک تاریخ، یک آرایه، یک مجموعه و یا هر شیء پیچیده ی دیگه ای اشاره کنه، تا زمانی که اون متغیر در کدتون وجود داره و قابلِ آدرس دهی هست، شیء مورد نظرش در دسترس خواهد بود.
بذارید کمی واضحتر توضیح بدم،  زمانی که در زبان جاوا متغیری مثلا از نوع integer تعریف می کنیم، این متغیر و مقدار آن به صورت مستقیم داخل حافظه Stack ذخیره می شه و دسترسی ما به مقدار آن متغیر، به طور مستقیم از داخل حافظه Stack هست، اما زمانی که شئ ای از نوع یک کلاس ایجاد می کنیم، خانه ای برای اون متغیر در حافظه ی Stack ایجاد شده و شئ مربوط به آن متغیر در حافظه ی Heap ذخیره میشه، سپس در قسمت مربوط به متغیر در حافظه ی Stack، آدرس شئ ایجاد شده در حافظه ی Heap ذخیره می شود. اصطلاحاً به مورد اول Value Type و به مورد دوم  Reference Type می گویند.

مدیریت اتوماتیک حافظه در جاوا
مدیریت اتوماتیک حافظه در جاوا

اما شیوه دسترسی به متغیرهای Value Type و Reference Type چطوری هست؟
زمانی که ما قصد دسترسی به متغیری، از نوع Value Type رو داریم؛ مقدار اون به صورت مستقیم از داخل حافظه Stack خوانده می شه، اما برای متغیرهای Reference Type، ابتدا به Stack رفته و پس از خوندن آدرس اون در Heap، به حافظه Heap مراجعه شده و شئ مربوط به اون خونده می شه. با این تفاسیر، وقتی متغیری از نوع Reference Type (متغیر هایی که در Heap ذخیره می شن ) را معادل متغیر دیگری قرار می دهیم، قسمت جدیدی برای اون در حافظه Stack ایجاد شده، و آدرس متغیر قبلی رو داخل اون قرار می دهد. این یعنی که اگر هر کدام از پارامترهای متغیرها تغییر کنند، متغیر دیگر هم تغییر می کند.

شیوه دسترسی به متغیرهای Value Type و Reference Type
شیوه دسترسی به متغیرهای Value Type و Reference Type

زمانی که همه ی ارجاعات به متغیر منقضی شدند،
برای رفتن به garbage collection یا مجموعه آشغال ها، واجدِ شرایط هست و آماده می باشد.

garbage collection یا مدیریت اتوماتیک حافظه مجموعه آشغال ها در جاوا
garbage collection یا مدیریت اتوماتیک حافظه مجموعه آشغال ها در جاوا

زمان انجام منقضی نمودن ارجاعات

ولی الان مهم این هست که فرایند Garbage Collector تصمیم بگیره چه زمانی اینکار رو انجام بدهد.
متغیر هایی که در داخلِ متدها یا در داخلِ بلوک های کد تعریف کردید با مشخص کردن دامنه یا حوزه ی مربوط به اون بلوک منقضی می شوند.
در اسلاید تصویر زیر یک مثال آوردم تا بهتر متوجه بشید.
بذارید بگم که یک متد دارم با نامه changeString و در این متد یک متغیر با نام localVar تعریف کردم. دامنه تعریف این متغیر متد اون هست، و به محض اینکه کار متد تمام شود، این متغیر هم منقضی می شود.
بریم سراغ مقدار متغیر، شیء ای که به اون ارجاع داده شده بود، ممکن هست برای مدتی در حافظه نگه داشته شود، ولی از آدرس در هیچ جا نمی توانید استفاده کنید. پس این متغیر آماده هست برای اینکه به garbage collection برود؛ و دفعه بعد که Garbage Collector دنبال متغیرهای قابل حذف از حافظه بگردد، این متغیر را انتخاب می کند و ممکن هست تصمیم بگیرد که حذفش کند و حافظه رو برای استفاده های بعدی پاک و اصلاح کند.

زمان منقضی نمودن ارجاعات در جاوا
زمان منقضی نمودن ارجاعات در جاوا

 همچنین می توانید متغیر ها را با استفاده از کلمه کلیدی null که تمامیِ حروفش با حروف کوچیک اسپل شده باشد؛ منقضی کنید.
اگر کد موجود در تصویر زیر رو اجرا کنم؛ یا یک رشته رو معرفی کنم و بعد بلافاصله مقدار اون متغیر را null بگذارم، بدون توجه به حوزه تعریف متغیر، اون متغیر را منقضی کرده ام.
یبار دیگه میگم که، این شیء می تواند همچنان برای یک مدت کوتاه در حافظه باقی بماند ولی نمی توانید أزش استفاده کنید.

رد کردن بطور صریح متغیرها در جاوا با کلمه کلیدی null
رد کردن بطور صریح متغیرها در جاوا با کلمه کلیدی null

garbage collector در جاوا

Garbage Collector در نخ مربوط به خودش اجرا میشه.
بسته به نوع برنامه ای که می خواهید اجرا کنید و بسته به سخت افزارتان، میزان حافظه و بقیه منابع در دسترس، فرآیند Garbage Collector تصمیم می گیرد که چه چیزهایی را از حافظه پاک کند. معمولاً موقع اجرا با کمی مکث مواجه می شوید.
 ماهیت Garbage Collector این هست که می تواند اشیای منقضی را پاک کند و حافظه را اصلاح و پاک کند.
البته اینم بگم که مجبور به این کار نیست. Garbage Collector یک فرایند هوشمند هست، یعنی برای خودش اجرا می شود؛ و شما به عنوان یک برنامه نویس نمی توانید تأثیر چندانی در نحوه کار اون داشته باشید.
یعنی مثلاً نمی توانید garbage collection را مجبور به انجام کاری کنید. و نمی توانید بگید من می خوام این شیء خاص از حافظه ام پاک شود.

garbage collector در جاوا
garbage collector در جاوا

متدهای سیستم در جاوا و معرفی exception از نوع OutOfMemoryError

تنها کاری که می توانید انجام دهید این هست که متدهایی که به garbage collection نیاز دارند را اجرا کنید.
ولی تضمینی وجود ندارد که این اتفاق بیافتد و اطمینانی نیست که اون شیء خاص مدنظر ما پاک شود.
این خیلی مهم هست که بدانید، وقتی ماشین مجازی جاوا برنامه ای را که از میزان حافظه بیش از حد، دارد استفاده می کند را اجرا می کند؛ چه اتفاقی در جاوا می افتد.
ما در طول این دوره، در مورد استثناءها صحبت خواهبم کرد. یک exception یا استثناء یک ارورِ، زمان-اجرا هست. چیزی که گاهی منجر به این می شود که اجرای برنامه متوقف یا crash شود و با مشکل مواجه شویم. که گاهاً به fatal exception یا استثناء مخرب معروف هست. اگر ماشین مجازی جاوا برنامه ای را که به حافظه بیش از حد نیاز دارد اجرا کند، می تواند منجر به این exception شود، و میگه OutOfMemoryError. که می تواند منجر به این شود که کل برنامه و یا حتی ماشین مجازی آن متوقف شود.

متدهای سیستم در جاوا و معرفی exception از نوع OutOfMemoryError
متدهای سیستم در جاوا و معرفی exception از نوع OutOfMemoryError

نکات قابل توجه برای مدیریت حافظه در جاوا

برای جلوگیری از چنین اتفاقی، باید کمی راجب به مدیریت حافظه در برنامه های جاوا یاد بگیرید.
اول از همه آنچه که باید بعنوانِ یک برنامه نویس انجام بدهید، به حداقل رساندن تعداد اشیائی هست که می سازید.
وقتی می خواهید شروع کنید به ایجاد اشیاء، قبل از آن ببینید می شود راهی پیدا کرد که بشود بجای ایجاد یک نوع جدید، اون اشیاء رو بازیابی کرد یا بشه اونها را مجدد استفاده کرد.
 اگر مطمئن نیستید که برنامه تان دچار مشکل شده، می توانید از این متدها استفاده کنید.
 اول از همه، کلاس رانتایم یک متد دارد با نام maxMemory، و همچنین همون کلاس رانتایم؛ یک متدِ دیگه دارد با نام totalMemory. این می تواند به شما بگوید چه مقدار از حافظه به ماشین مجازی اختصاص یافته است، و چه مقدار از حافظه در حالِ حاضر در دسترس و  قابل استفاده است.

نکات قابل توجه برای مدیریت حافظه در جاوا
نکات قابل توجه برای مدیریت حافظه در جاوا

تنظیم حافظه در دسترس زبان جاوا

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

تنظیم حافظه در دسترس زبان جاوا
تنظیم حافظه در دسترس زبان جاوا

 می توانید مقادیر موجود در تصویر فوق را امتحان کنید، و حتی می توناید از طریقِ راهنما و مستنداتِ موجودِ جاوا هم اطلاعات بیشتری در مورد مدیریت حافظه در جاوا بدست بیارید. بد نیست اینم بدونید که این روش ها از یک پلتفرم به پلتفرم دیگر می تواند متفاوت باشند.
تنظیمات پیشنهادی در یک محیط از نسخه ی Enterprise یا سازمانی جاوا می تواند با تنظیماتِ پیشنهادی در یک دستگاه اندرویدی خیلی تفاوت کند. بنابراین باز هم ذکر می کنیم که، اسناد و اطلاعات را چک کنید، و از سایر توسعه دهنده ها در زمینه کاری خودتون سؤال کنید و نظراتشونو بپرسید، و آنقدر برنامه خودتان را امتحان کنید، تا حافظه ی کاربردی با دقت بالایی ایجاد کنید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دوره ها
درس ها
طهاکو من
0