JavaRush /مدونة جافا /Random-AR /دورة حياة الكائن

دورة حياة الكائن

نشرت في المجموعة
مرحبًا! أعتقد أنك لن تتفاجأ كثيرًا إذا أخبرناك أن حجم الذاكرة على جهاز الكمبيوتر الخاص بك محدود :) حتى محرك الأقراص الثابتة، وهو أكبر بعدة مرات من ذاكرة الوصول العشوائي، يمكن ملؤه بألعابك المفضلة ومسلسلاتك التلفزيونية، وما إلى ذلك وهلم جرا. لمنع حدوث ذلك، تحتاج إلى مراقبة الحالة الحالية للذاكرة وحذف الملفات غير الضرورية من جهاز الكمبيوتر الخاص بك. ما علاقة برمجة جافا بكل هذا؟ مباشر! بعد كل شيء، عندما يتم إنشاء أي كائن بواسطة جهاز Java، يتم تخصيص ذاكرة له. في برنامج كبير حقيقي، يتم إنشاء عشرات ومئات الآلاف من الكائنات، ولكل منها جزء خاص به من الذاكرة. دورة حياة الكائن - 1ولكن إلى متى تعتقد أن كل هذه الأشياء موجودة؟ هل "يعيشون" طوال فترة تشغيل برنامجنا؟ بالطبع لا. مع كل مزايا كائنات Java، فهي ليست خالدة :) الكائنات لها دورة حياتها الخاصة. اليوم سنأخذ استراحة قصيرة من كتابة التعليمات البرمجية وننظر إلى هذه العملية :) علاوة على ذلك، فهي مهمة جدًا لفهم تشغيل البرنامج وإدارة الموارد. إذًا، أين تبدأ حياة الجسم؟ كالإنسان منذ ولادته أي الخلق.
Cat cat = new Cat();//вот сейчас и начался vital цикл нашего an object Cat!
أولاً، يقوم Java Virtual Machine بتخصيص مقدار الذاكرة اللازم لإنشاء الكائن. ثم تقوم بإنشاء رابط إليه، في حالتنا، 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()يتوقف كائن سيارة Lamborghini Diablo عن الحياة بالفعل في السطر الثاني. لم يكن هناك سوى رابط واحد له، والآن تم تخصيص هذا الرابط null. نظرًا لعدم وجود أي إشارات متبقية إلى لامبورجيني ديابلو، فقد أصبحت "غير مرغوب فيها". ليس من الضروري إعادة ضبط الرابط:
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وخصصناه لهذا الكائن الجديد. يوجد الآن Lamborghini Gallardoمرجعان يشيران إلى الكائن، لكن Lamborghini Diabloلا يوجد أي مرجع إلى الكائن. وبالتالي يصبح الكائن Diabloالقمامة. وفي هذه اللحظة، يتم تشغيل آلية Java المدمجة، والتي تسمى جامع البيانات المهملة، أو بمعنى آخر - Garbage Collector، GC.
دورة حياة الكائن - 2
أداة تجميع البيانات المهملة هي آلية Java داخلية مسؤولة عن تحرير الذاكرة، أي إزالة الكائنات غير الضرورية منها. لم يكن من قبيل الصدفة أننا اخترنا صورة باستخدام مكنسة كهربائية روبوتية لتصويرها. بعد كل شيء، يعمل جامع البيانات المهملة بنفس الطريقة تقريبًا: في الخلفية، "يسافر" عبر برنامجك، ويجمع القمامة، وفي نفس الوقت لا تتفاعل معه عمليًا. وتتمثل مهمتها في إزالة الكائنات التي لم تعد مستخدمة في البرنامج. وبالتالي، فإنه يحرر الذاكرة في الكمبيوتر لأشياء أخرى. هل تتذكر في بداية المحاضرة قلنا أنه في الحياة العادية عليك مراقبة حالة جهاز الكمبيوتر الخاص بك وحذف الملفات القديمة؟ لذلك، في حالة كائنات Java، يقوم جامع البيانات المهملة بذلك نيابةً عنك. يتم تشغيل Garbage Collector عدة مرات أثناء تشغيل برنامجك: لا يلزم استدعاؤه على وجه التحديد وإعطائه أوامر، على الرغم من أن هذا ممكن من الناحية الفنية. سنتحدث لاحقًا عنها أكثر ونحلل عملية عملها بمزيد من التفصيل. في اللحظة التي يصل فيها جامع البيانات المهملة إلى الكائن، قبل تدميره مباشرة، يتم استدعاء طريقة خاصة على الكائن - finalize(). يمكن استخدامه لتحرير بعض الموارد الإضافية التي كان يستخدمها الكائن. الطريقة finalize()تنتمي إلى الفصل Object. وهذا يعني أنه بالإضافة إلى equals()و hashCode()و toString()، التي التقيت بها مسبقًا، فإن أي كائن يمتلكها. اختلافها عن الطرق الأخرى هو أنها... كيف يمكن التعبير عن ذلك... متقلبة للغاية. أي أنه لا يتم استدعاؤه دائمًا قبل تدمير الكائن. البرمجة شيء دقيق. يخبر المبرمج الكمبيوتر أن يفعل شيئًا ما، والكمبيوتر يفعل ذلك. من المحتمل أنك معتاد بالفعل على هذا السلوك، وقد يكون من الصعب عليك في البداية قبول الفكرة: "قبل تدمير الكائنات، تسمى طريقة finalize()الفصل Object. أو لا يسمى. إذا حالفنا الحظ!" ومع ذلك، هذا صحيح. يحدد جهاز Java نفسه ما إذا كان سيتم استدعاء الطريقة 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;//вот здесь первый an object становится доступен сборщику мусора
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("Объект Cat уничтожен!");
   }
}
نقوم بإنشاء كائن Catوفي السطر التالي من التعليمات البرمجية نقوم بإعادة تعيين المرجع الوحيد له. وهكذا - مليون مرة. لقد قمنا بتجاوز الطريقة بشكل صريح finalize()، ويجب أن تطبع السلسلة النصية على وحدة التحكم مليون مرة، في كل مرة قبل تدمير الكائن Cat. لكن لا! على وجه الدقة، تم تشغيله 37346 مرة فقط على جهاز الكمبيوتر الخاص بي! وهذا يعني أنه في حالة واحدة فقط من أصل 27 حالة، قرر جهاز Java الذي قمت بتثبيته استدعاء طريقة ما finalize()- وفي حالات أخرى، تم تنفيذ عملية جمع البيانات المهملة بدون ذلك. حاول تشغيل هذا الرمز بنفسك: على الأرجح ستكون النتيجة مختلفة. كما ترون، finalize()من الصعب أن نسميها شريكًا موثوقًا :) لذلك، نصيحة صغيرة للمستقبل: لا تعتمد على الطريقة finalize()في حالة تحرير بعض الموارد المهمة. ربما سيتصل به JVM، وربما لا. من تعرف؟ إذا كان الكائن الخاص بك أثناء حياته يشغل بعض الموارد التي كانت ذات أهمية كبيرة للأداء، على سبيل المثال، فقد احتفظ باتصال مفتوح بقاعدة البيانات، فمن الأفضل إنشاء طريقة خاصة في فصلك لتحريرها واستدعائها بشكل صريح عندما يكون الكائن لم تعد هناك حاجة. بهذه الطريقة ستعرف على وجه اليقين أن أداء برنامجك لن يتأثر. في البداية قلنا أن إدارة الذاكرة وإزالة البيانات المهملة مهمان جدًا، وهذا صحيح. يمكن أن يؤدي التعامل غير المناسب مع الموارد وعدم فهم عملية تجميع الكائنات غير الضرورية إلى تسرب الذاكرة. وهذا من أشهر الأخطاء البرمجية. يمكن أن تؤدي التعليمات البرمجية المكتوبة بشكل غير صحيح من قبل المبرمج إلى تخصيص ذاكرة جديدة في كل مرة للكائنات التي تم إنشاؤها حديثًا، في حين أن الكائنات القديمة غير الضرورية غير متاحة للإزالة بواسطة أداة تجميع البيانات المهملة. نظرًا لأننا أجرينا تشبيهًا بالمكنسة الكهربائية الروبوتية، تخيل ما سيحدث إذا قمت، قبل تشغيل الروبوت، بتوزيع الجوارب في جميع أنحاء المنزل، وكسرت مزهرية زجاجية وتركت مجموعة ليغو مفككة على الأرض. سيحاول الروبوت، بطبيعة الحال، أن يفعل شيئًا ما، لكنه سيتعثر عند نقطة ما.
دورة حياة الكائن - 3
لكي تعمل بشكل صحيح، تحتاج إلى الحفاظ على الأرضية في حالة جيدة وإزالة كل شيء لا تستطيع المكنسة الكهربائية التعامل معه. يعمل جامع القمامة على نفس المبدأ. إذا كان هناك العديد من العناصر المتبقية في البرنامج والتي لا يمكنه جمعها (مثل جورب أو قطع الليغو للمكنسة الكهربائية الروبوتية)، فسوف تنفد الذاكرة عند نقطة ما. ولن يتم تجميد البرنامج الذي كتبته فحسب، بل سيتم أيضًا تجميد جميع البرامج الأخرى التي تعمل على الكمبيوتر في تلك اللحظة. لن تكون هناك ذاكرة كافية لهم أيضًا. هذا هو ما تبدو عليه دورة حياة الكائن ومجمع البيانات المهملة في Java. ليست هناك حاجة لحفظ هذا: فقط افهم مبدأ التشغيل. في المحاضرة التالية، سنتحدث عن هذه العمليات بمزيد من التفصيل، لكن في الوقت الحالي يمكنك العودة إلى حل مشكلات JavaRush :) حظًا سعيدًا!
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION