مقدمة
لقد رأيت سؤالاً عن SegmentFault: Java لديها آلية GC كاملة ، لذلك ستكون هناك مشكلة في تسرب الذاكرة في Java ، وهل يمكنني إعطاء حالة من تسرب الذاكرة. يعطي عرض السؤال هذا الإجابة الكاملة على هذا السؤال.
مقدمة لآلية إعادة تدوير القمامة
أثناء تشغيل البرنامج ، يتم إنشاء كل كائن ، يتم تخصيص كمية معينة من الذاكرة لتخزين بيانات الكائن. إذا استمرت فقط في تخصيص الذاكرة ، فسيواجه البرنامج مشكلة عدم كفاية الذاكرة عاجلاً أم آجلاً. لذلك ، في أي لغة ، ستكون هناك آلية لاستعادة الذاكرة لتحرير ذاكرة الكائنات المنتهية لضمان إعادة استخدام الذاكرة.
يمكن تقسيم آلية إعادة تدوير الذاكرة إلى نوعين وفقًا لأدوار التنفيذ. أحدهما هو أن المبرمجين يدركون يدويًا إصدار الذاكرة (مثل لغة C) والآخر هو آلية إعادة تدوير الذاكرة المدمجة للغة ، مثل آلية جمع القمامة Java التي سيتم تقديمها في هذه المقالة.
آلية جمع القمامة جافا
في بيئة وقت التشغيل للبرنامج ، يوفر جهاز Java Virtual Machine مجموعة من مجموعة القمامة على مستوى النظام (GC ، Carbage Collection) ، المسؤول عن استعادة الذاكرة التي تشغلها كائنات فقدت المراجع. الشرط المسبق لفهم GC هو فهم بعض المفاهيم المتعلقة بجمع القمامة. يتم تقديم هذه المفاهيم واحدة تلو الأخرى في ما يلي.
حالة الكائن في منطقة كومة JVM
يتم تخزين مثيلات كائنات Java في منطقة كومة JVM. بالنسبة لخيوط GC ، تحتوي هذه الكائنات على ثلاث حالات.
1. حالة قابلة لللمس: هناك مراجع متغيرة في البرنامج ، لذلك هذا الكائن هو حالة قابلة لللمس.
2. الحالة التي تم إعادة تنشيطها: عندما لا تشير أي متغيرات في البرنامج إلى هذا الكائن ، سيتغير الكائن من حالة قابلة للمس إلى حالة إعادة تنشيطها. سيستعد مؤشر ترابط CG لاستدعاء طريقة النهائيات لهذا الكائن في وقت معين (ترث طريقة اللمسات الأخيرة أو إعادة كتابة كائن الطفل). قد يقوم الكود في طريقة الانتهاء بتحويل الكائن إلى حالة قابلة للمس ، وإلا فإن الكائن سيتم تحويله إلى حالة لا يمكن المساس بها.
3. الحالة التي لا يمكن المساس بها: يمكن لخيط GC إعادة تدوير ذاكرة هذا الكائن فقط عندما يكون الكائن في حالة لا يمكن المساس بها.
من أجل تحرير الكائنات بشكل صحيح ، يجب على GC مراقبة حالة تشغيل كل كائن ، بما في ذلك التطبيق ، والاستشهاد ، والاستشهاد ، والتعيين ، وما إلى ذلك. يحتاج GC إلى مراقبته ، لذلك ستعرف GC بغض النظر عما إذا كان الكائن في أي حالة أعلاه.
كما ذكر أعلاه ، ستقوم مؤشرات ترابط GC بتنفيذ طريقة الانتهاء من كائنات الحالة القابلة للإحياء في وقت معين. إذن متى سيتم تنفيذها؟ نظرًا لأن منفذي JVM المختلفون قد يستخدمون خوارزميات مختلفة لإدارة GC ، في أي وقت ، لا يمكن للمطورين التنبؤ بتوقيت مؤشرات ترابط GC التي تنفذ عمليات مختلفة (بما في ذلك اكتشاف حالة الكائن ، وإطلاق ذاكرة الكائن ، واتصال الكائنات اللمسات الأخيرة على الأساليب). على الرغم من أنه يمكن تذكير مؤشر ترابط GC بأداء عمليات جمع القمامة في أقرب وقت ممكن من خلال وظائف System.gc () ووقت Runtime.gc () ، فإن هذا لا يمكن أن يضمن أن مؤشر ترابط GC سيؤدي عمليات إعادة التدوير المقابلة على الفور.
تسرب الذاكرة
تحدث تسرب الذاكرة بسبب التصميمات الخاطئة التي يفشلها البرنامج في إطلاق ذاكرة لم تعد تستخدم ، مما يؤدي إلى مضيعة للموارد. ستقوم GC تلقائيًا بتنظيف الذاكرة التي تشغلها كائنات فقدت المراجع. ومع ذلك ، إذا تم الرجوع دائمًا إلى بعض الكائنات بسبب أخطاء البرمجة ، فسيحدث تسرب الذاكرة.
على سبيل المثال ، المثال التالي. يتم استخدام صفيف لتنفيذ مكدس ، مع عمليتين: إدخال المكدس والخروج المكدس.
استيراد com.sun.javafx.collections.elementobservablistdecorator ؛ import com.sun.swing.internal.plaf.metal.resources.metal_sv ؛ import java.beans.exceptionlistener ؛ java.util.emptystaceception ؛/** ** ** beng on 14-9 -21. */الفئة العامة Mystack {private object [] elements ؛ زيادة int الخاصة = 10 ؛ حجم int الخاص = 0 ؛ Mystack العام (int size) {elements = كائن جديد [size] ؛ } // ضع المكدس public void push (object o) {cute () ؛ عناصر [size ++] = o ؛ } // ضع الكائن العام المكدس pop () {if (size == 0) رمي فارغ stackexception () ؛ إرجاع عناصر [-الحجم] ؛ } // زيادة قدرة سعة الفراغ الخاصة المكدس () {if (elements.length! = size) return ؛ Object [] NewArray = كائن جديد [Elements.Length + Gradement] ؛ System.ArrayCopy (عناصر ، 0 ، نياراي ، 0 ، الحجم) ؛ } public static void main (string [] args) {mystack stack = new mystack (100) ؛ لـ (int i = 0 ؛ i <100 ؛ i ++) stack.push (عدد صحيح جديد (i)) ؛ لـ (int i = 0 ؛ i <100 ؛ i ++) {system.out.println (stack.pop (). toString ()) ؛ }}}هذا البرنامج متاح ويدعم عمليات الإدخال المشتركة ومكدس الدخول. ومع ذلك ، هناك مشكلة لم يتم التعامل معها بشكل جيد ، أي عندما يتم إصدار عملية المكدس ، لم يتم إطلاق إشارة إلى عنصر المكدس في الصفيف ، مما يؤدي إلى الاحتفاظ بالبرنامج مرجعًا إلى هذا الكائن (تتم الإشارة إلى هذا الكائن بواسطة الصفيف). تعتقد GC دائمًا أن هذا الكائن يمكن الوصول إليه ، مما يعني أنه لا توجد حاجة للحديث عن إطلاق ذاكرته. هذه حالة نموذجية من تسرب الذاكرة. لهذا ، الكود المعدل هو:
// stack public object pop () {if (size == 0) refl reparestackexception () ؛ كائن o = عناصر [-الحجم] ؛ عناصر [الحجم] = فارغة ؛ العودة س ؛ }المقالة أعلاه لها فهم عميق لآلية جمع القمامة Java وتسرب الذاكرة. هذا هو كل المحتوى الذي شاركته معك. آمل أن يعطيك مرجعًا وآمل أن تتمكن من دعم wulin.com أكثر.