CodeGym /وبلاگ جاوا /Random-FA /چرخه حیات شی
John Squirrels
مرحله
San Francisco

چرخه حیات شی

در گروه منتشر شد
سلام! فکر می کنم خیلی تعجب نخواهید کرد اگر به شما بگویم که رایانه شما حافظه محدودی دارد :)
چرخه حیات شی - 1
حتی هارد دیسک شما (که چندین برابر رم است) می تواند مملو از بازی های مورد علاقه، برنامه های تلویزیونی و چیزهای دیگر شما باشد. برای جلوگیری از این اتفاق، باید وضعیت فعلی حافظه رایانه خود را کنترل کرده و فایل های غیر ضروری را حذف کنید. همه اینها چه ارتباطی با برنامه نویسی جاوا دارد؟ کاملا مستقیم! از این گذشته، ایجاد هر شیئی باعث می شود که ماشین جاوا حافظه ای را برای آن اختصاص دهد . یک برنامه بزرگ در دنیای واقعی ده ها یا صدها هزار شی را ایجاد می کند و برای هر یک از آنها یک تکه حافظه اختصاص می یابد. اما به نظر شما چه تعداد از این اشیاء وجود دارد؟ آیا آنها در تمام مدت اجرای برنامه ما "زنده" هستند؟ البته که نه. حتی با تمام مزایایی که دارند، اشیاء جاوا جاودانه نیستند :) اشیا چرخه حیات خود را دارند. امروز کمی از نوشتن کد فاصله می گیریم و این فرآیند را بررسی می کنیم :) همچنین برای درک نحوه کار یک برنامه و مدیریت منابع بسیار مهم است. بنابراین، زندگی یک شی از کجا شروع می شود؟ مانند انسان از بدو تولد، یعنی زمانی که خلق می شود.
Cat cat = new Cat();// Our Cat object's lifecycle begins now!
ابتدا ماشین مجازی جاوا حافظه لازم برای ایجاد شی را اختصاص می دهد. سپس یک مرجع به آن ایجاد می کند (در مورد ما، cat) تا امکان پیگیری آن را فراهم کند. سپس همه متغیرها مقداردهی اولیه می شوند، سازنده فراخوانی می شود، و شی تازه ما اکنون زندگی خود را دارد :) طول عمر شی متفاوت است. در اینجا ارقام دقیقی وجود ندارد. در هر صورت، یک شی در برنامه زندگی می کند و عملکردهای خود را برای مدتی انجام می دهد. به طور دقیق، شی «زنده» است تا زمانی که اشاره هایی به آن وجود داشته باشد. به محض اینکه هیچ مرجعی وجود ندارد، شی "می میرد". مثلا:
public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}
در این main()روش، شیء ماشین "لامبورگینی دیابلو" در خط دوم زنده نمی ماند. تنها یک مرجع به آن وجود داشت و مرجع صفر تعیین شد. از آنجایی که هیچ مرجعی به دیابلو وجود ندارد، به "زباله" تبدیل می شود. لازم نیست یک مرجع روی صفر تنظیم شود تا این اتفاق بیفتد:
public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}
در اینجا ما یک شیء دوم ایجاد کرده ایم و آن را به مرجع لامبورگینی اختصاص می دهیم. اکنون دو مرجع به Lamborghini Gallardoشی اشاره می کنند، اما Lamborghini Diabloشی هیچ کدام را ندارد. این بدان معنی است که Diabloجسم به زباله تبدیل می شود. این زمانی است که زباله جمع‌کننده داخلی جاوا (GC) وارد عمل می‌شود.
چرخه حیات شی - 2
زباله جمع کن یک مکانیسم داخلی جاوا است که مسئول آزاد کردن حافظه است، یعنی حذف اشیاء غیر ضروری از حافظه. دلیلی وجود دارد که چرا ما آن را با جاروبرقی روباتی معرفی کردیم. زباله جمع کن تقریباً به همین روش کار می کند: برنامه شما را در پس زمینه "حرکت می کند" و زباله ها را جمع آوری می کند. شما عملا نیازی به تعامل با آن ندارید. وظیفه آن حذف اشیایی است که دیگر در برنامه استفاده نمی شوند. بنابراین، حافظه را برای اشیاء دیگر آزاد می کند. آیا به یاد دارید که در ابتدای درس گفتیم در زندگی واقعی باید وضعیت رایانه خود را کنترل کنید و فایل های قدیمی را حذف کنید؟ اگر در مورد اشیاء جاوا صحبت می کنیم، جمع کننده زباله این کار را برای شما انجام می دهد . جمع‌آوری زباله چندین بار در حین اجرای برنامه شما شروع به کار می‌کند: لازم نیست صریحاً آن را فراخوانی کنید و به آن دستور دهید (اگرچه از نظر فنی این امکان وجود دارد). بعداً در مورد زباله جمع کن بیشتر صحبت خواهیم کرد و نحوه عملکرد آن را با جزئیات بیشتری تحلیل خواهیم کرد. هنگامی که زباله جمع کن به یک شی می رسد - درست قبل از تخریب - finalize()روش خاص آن شی نامیده می شود. این روش می تواند برای آزاد کردن منابع اضافی خاص مورد استفاده توسط شی مورد استفاده قرار گیرد. متد finalize()متعلق به کلاس Object است. به عبارت دیگر، شبیه به و (که قبلاً با آن equals()آشنا شده اید) است . هر شیئی آن را دارد . فرقش با روش های دیگه اینه که...چطور باید اینو بگیم...خیلی عمدیه. منظور ما این است که همیشه قبل از تخریب یک شیء فراخوانی نمی شود . برنامه نویسی یک فعالیت بسیار دقیق است. برنامه نویس به کامپیوتر می گوید کاری را انجام دهد و کامپیوتر آن را انجام می دهد. من فرض می‌کنم که شما به این نوع رفتار عادت کرده‌اید، بنابراین در ابتدا ممکن است قبول این ایده برای شما دشوار باشد: "قبل از اینکه یک شی از بین برود، متد کلاس Object فراخوانی می‌شود. یا خیر. اگر ما خوش شانس باشیم! " با این حال، این واقعیت است. خود ماشین جاوا تعیین می‌کند که آیا finalize() را به صورت موردی فراخوانی کند. به عنوان یک آزمایش، بیایید کد زیر را اجرا کنیم: hashCode()toString()finalize()
public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {

       for (int i = 0 ; i < 1000000; i++) {

           Cat cat = new Cat();
           cat = null;// The first object becomes available for garbage collection here
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("The Cat is destroyed!");
   }
}
یک شی ایجاد می کنیم Catو در خط بعدی تنها مرجع آن را صفر می کنیم. و ما این کار را میلیون ها بار انجام می دهیم. ما به صراحت finalize()روش را لغو کرده ایم. هر بار که یک Catشی از بین می رود، باید یک رشته نمایش دهد - در مجموع یک میلیون بار. اما نه! به طور دقیق، در کامپیوتر من فقط 37346 بار اجرا شد ! به عبارت دیگر، ماشین جاوا من تصمیم گرفت که finalize()از هر 27 مورد فقط 1 مورد را فراخوانی کند. در موارد دیگر، جمع آوری زباله شامل این تماس نمی شد. خودتان این کد را اجرا کنید. به احتمال زیاد نتیجه متفاوتی خواهید گرفت. همانطور که می بینید، تماس با finalize()یک شریک قابل اعتماد دشوار است :) بنابراین، در اینجا یک نکته کوچک برای آینده وجود دارد: به روشی finalize()برای انتشار منابع حیاتی اعتماد نکنید. ممکن است JVM آن را صدا کند، یا نه. چه کسی می داند؟ اگر شیء شما برخی از منابع حیاتی عملکرد (مثلاً یک اتصال پایگاه داده باز) را در حالی که زنده بود در خود نگه می داشت، بهتر است یک متد خاص ایجاد کرده و صریحاً فراخوانی کنید تا در زمانی که دیگر به شی مورد نیاز نیست، آنها را آزاد کنید. به این ترتیب، مطمئناً متوجه خواهید شد که عملکرد برنامه شما آسیب نخواهد دید. ما با گفتن این نکته شروع کردیم که کار با حافظه و جمع‌آوری زباله موضوعات بسیار مهمی هستند و واقعاً هم هستند. استفاده نادرست از منابع و درک نادرست از نحوه تمیز کردن اشیاء غیر ضروری می تواند منجر به یکی از ناخوشایندترین اشکالات شود: نشت حافظه . این یکی از شناخته شده ترین خطاهای برنامه نویسی است. حتی مقاله ویکی پدیا خود را دارد . کد نوشته شده ضعیف می تواند موقعیتی ایجاد کند که در آن حافظه هر بار برای اشیاء تازه ایجاد شده تخصیص داده شود، اما اشیاء قدیمی و غیر ضروری برای جمع آوری زباله در دسترس نیستند. از آنجایی که قبلاً شبیه ربات جاروبرقی را انجام داده‌ایم، تصور کنید چه اتفاقی می‌افتد اگر قبل از اجرای ربات جوراب‌ها را در سراسر خانه پراکنده کنید، یک گلدان شیشه‌ای را بشکنید و قطعات لگو را در سرتاسر زمین رها کنید. به طور طبیعی، ربات سعی می کند کاری انجام دهد، اما یک روز آن را تصرف می کند.
چرخه حیات شی - 3
برای اینکه جاروبرقی به درستی کار کند، باید کف را در شکل مناسبی نگه دارید و هر چیزی را که از عهده آن بر نمی آید، بردارید. زباله جمع کن از همین اصل پیروی می کند. اگر برنامه ای اشیاء زیادی داشته باشد که نمی تواند آنها را تمیز کند (مانند جوراب یا لگو برای جاروبرقی روباتیک ما)، یک روز حافظه ما تمام می شود. نه تنها برنامه شما هنگ می کند، بلکه سایر برنامه هایی که روی رایانه اجرا می شوند نیز متوقف می شوند. از این گذشته، آنها نیز حافظه کافی نخواهند داشت (با بازگشت به قیاس ما، شیشه شکسته روی زمین نه تنها جاروبرقی، بلکه افرادی را که در خانه زندگی می کنند نیز متوقف می کند). به طور خلاصه، این چیزی است که چرخه زندگی اشیا و جمع آوری زباله در جاوا به نظر می رسد. لازم نیست این را به خاطر بسپارید: کافی است به سادگی نحوه عملکرد آن را درک کنید. در درس بعدی، با جزئیات بیشتر به این فرآیندها باز خواهیم گشت. اما در حال حاضر، شما می توانید به حل وظایف CodeGym بازگردید :) موفق باشید!
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION