‫چرا نباید در جاوا از متده finalize استفاده کنیم ؟

finalize method - ‫متده finalize

‫امروز میخوایم در مورد کارایی متده finalize صحبت کنیم . این متد در داخل کلاسه Object وجود داره لذا چون پدر همه ی کلاس های جاوایی کلاسه Object است همه کلاس های جاوایی اون رو دارند.

‫کار این متد اینه که به JVM این کمک رو میکنه که وقتی مکانیزم Garbage Collection احساس کرد که دیگه Reference ی به یک Object وجود نداره اون فضای مموری رو آزاد کنه

‫خیلی راحت برای اینکه بفهمین چطوری کار میکنه یک کلاس بنویسید و یک فایلی رو تو برنامه هه باز کنین ولی مثلا Reader رو توی بخش final عه catch نیاین close کنین.
‫همانطور که میدونین وقتی یک Stream رو باز کنین ولی فراموش کنین که ببندینش، این برای برنامه شما مشکل memory leak درست میکنه (چون نمیتونه فضای حافظه رو خالی کنه) و ممکنه باعث crash کردن برنامه شما بشه.

‫بعدش بیاین متده finalize رو تو اون کلاسه override کنین و stream رو توی این متده close کنین!
‫ در نهایت System.gc رو یجایی توی برنامتون بزنین ….

‫بعد با یه profiler مثل JVisualVM بیاین و از روی مموریتون قبل و بعد از اجرای متد override شده ی finalize تون Heap Dump بگیرین و از وجود Object عه stream تون اطمینان حاصل کنین. برای اینکه بفهمین که کی System.gc روی متده finalize عه اون object عه عملیات انجام میده میتونین یا یک break point بزارین و یا یه thread بزارین که چند ثانیه execution عه برنامه رو sleep کنه که بتونین روی profiler تون heap dump عه قبل و بعد رو تهیه کنین!

‫بدین شکل میتونین دقیقا بفهمین که finalize چطوری کار میکنه!

‫حالا برمیگردیم به سوال اصلی :
‫دوستان متد finaliz مشکلش چیه که برنامه نویسا نباید ازش استفاده کنند؟

‫ببینین در داخل Java دستوری وجود داره به نام System.gc که کارش اینه که به Garbage Collection دستور میده که مموری های غیر قابل استفاده رو آزاد کن برادر و وقتی که Java تشخیص بده که از یک Object توی مموری استفاده ای دیگه نمیشه یعنی هیچ جایی توی برنامه دیگه به اون شیء reference ی وجود نداره متده finalize و عه اون Object ترو فراخوانی میکنه تا از تو مموری بندازتش بیرون و فضای مموری را آزاد کنه

‫حالا نکات زیادی در مورد این System.gc وجود داره :
‫۱- تضمینی وجود نداره که وقتی که شما فراخوانیش میکنین همون لحظه اعمال بشه، شما در حقیقت این تسک رو میدین دست JVM ولی این JVM عه که تصمیم میگیره کی این تسکی که شما دادین بهش رو اجرا کنه

‫۲- این کار بسیار کار پر هزینه ای هستش برای JVM چون باید کلی فرایند داخلش انجام بشه و همیشه بهتره که دست خود JVM سپرده بشه این کار تا زمان درستش رو خودش تشخیص بده و انجامش بده

‫۳- با توجه به نکته ۱ شما نمیتونین تضمین بدین که دقیقا کی اون متده finalize فراخوانی میشه

‫۴- با توجه به نکته ۱ اگر قبل از اینکه JVM تصمیم بگیره GC رو فراخوانی کنه کل RAM پر بشه برنامه CRASH میکنه پس همیشه بهتره طوری برنامه نوشته بشه که بدرستی Resource ها آزاد بشن. مثلا توی مثال بالا باید توی catch یه final بزاریم و Stream رو close کنیم و یا از ویژگی try و catch عه با resource عه ارایه شده در JDK 7 به بعد استفاده کنیم

‫‫۵- دلیل اینکه میگن نباید از متد finalize استفاده کنین اینه که این متد یک متده System ی برای JVM هست و باید مدیریت این Garbage Collection گردن خوده JVM باشه نه شما چون اگر شما این متد رو خودتون مدیریت کنین ممکنه thread زنده ای که داره action عه مورد نظر رو انجام میده سرعت اجرای فرایند داخلی سیستم رو کند کنه (نه lock – فقط کند) و همچنین نکته ی دیگه ای که هست اینه که JVM در داخل دل خودش فرایندهای دیگه ای رو برای کنترل و مدیرت مموری انجام میده.

‫۶- وقتی که JVM تشخیص بده که همه thread های live ی که با یک Object در حال کار کردن هستند کشته شدند، اونوقته که تصمیم به free کردن حافظه میگیره و متده finalize اون Object مورد نظر رو فراخوانی میکنه

‫۷- همیشه این متد تنها یکبار توسط JVM فراخوانی میشه و نه بیشتر

‫۸- در داخل جاوا کلاس هایی وجود دارند که با Weak شروع میشن مثل WeakHashMap . با توجه به نکته شماره ۶ اگر JVM تشخیص بده که به یه Object یک Reference ی هست و thread ی براش هست که ممکنه آبجکت رو به چرخه کار برگردونه، متده finalize عه اون Object رو فراخوانی نمیکنه. حالا این کلاسهایی که در Java به نام Weak شناخته میشن به JVM میگن که آقای JVM تو به Reference هایی که از Object های دیگه به من هست توجه نکن و اگر دیدی Object ی وضعیت finalize شدن رو داره، حتی اگر به منم reference داره متده finalize ش رو فراخوانی کن و بندازش از تو مموری بیرون ….

‫۹- رفرنس های Phantom دقیقا برعکس Reference های Weak هستند و بیشتر برای Scheduling ها استفاده میشن و هیچوقت reference هاشون رو در اختیار garbage collection قرار نمیدن که GC بتونه اونارو پاک سازی کنه و مادامی که هم خود شیٔ و هم تمام referent های اون شیٔ بطور کامل غیرقابل استفاده نباشند توی مموری میمونند. از این مکانیزم بیشتر برای کارهای Schedling استفاده میشه و روشی منعطف تر از روشی کنترل مموری که خود جاوا توسط مکانیزم JVM در حالت عادی برای پاکسازی اون کارهای خاص انجام میده، دارند.

‫برای اطلاعات بیشتر از زبان خوده جاوا میتوانین به Specification عه زیر مراجعه کنید :
لینک

Published by

mehdi

I'm a Passionate Software Developer and Team Leader