عندما يتعلق الأمر بمجموعة Garbage (GC) ، فإن الكثير من الناس سوف يربطونها بشكل طبيعي مع Java. في Java ، لا يحتاج المبرمجون إلى الاهتمام بتخصيص الذاكرة الديناميكي وجمع القمامة ، ويتم ترك كل هذا إلى JVM للتعامل معه.
كما يوحي الاسم ، فإن مجموعة القمامة هي تحرير المساحة التي تشغلها القمامة. إذن في جافا ، ما نوع الأشياء التي ستعتبر "القمامة"؟ لذلك عندما يتم تحديد بعض الكائنات على أن تكون القمامة ، ما هي الإستراتيجية التي يجب استخدامها لإعادة التدوير (مساحة مجانية)؟ ما هي جامعي القمامة النموذجيين في الأجهزة الافتراضية التجارية الحالية؟ دعونا نناقش هذه القضايا واحدة تلو الأخرى. هنا هو الخطوط العريضة لهذا المقال:
كيف تحدد ما إذا كان كائن "القمامة"؟
خوارزمية جمع القمامة النموذجية جامع القمامة النموذجي
1. كيفية تحديد ما إذا كان كائن "القمامة"؟
في هذا القسم ، نفهم أولاً السؤال الأساسي: إذا حددنا أن كائن ما هو "القمامة"؟ نظرًا لأن مهمة جامع القمامة هي إعادة تدوير المساحة التي يشغلها كائن القمامة لاستخدامها من قبل كائنات جديدة ، كيف يحدد جامع القمامة أن الكائن هو "القمامة"؟ وهذا هو ، كيفية الحكم على أنه يمكن إعادة تدوير الجسم.
في Java ، يرتبط بالكائنات من خلال المراجع ، أي إذا كنت ترغب في تشغيل الكائنات ، فيجب أن يتم ذلك من خلال المراجع. ثم من الواضح أن طريقة سهلة هي الحكم على ما إذا كان يمكن إعادة تدوير كائن عن طريق العد المرجعي. دون فقدان عمومية ، إذا لم يكن للكائن أي مراجع مرتبطة به ، فهذا يعني أنه من غير المحتمل أن يتم استخدام الكائن في مكان آخر ، ثم يصبح الكائن كائنًا قابل لإعادة التدوير. تصبح هذه الطريقة طريقة العد المرجعية.
تتميز هذه الطريقة بتنفيذها البسيط وكفاءتها العالية ، لكنها لا يمكنها حل مشكلة المراجع الدائرية ، لذلك لا يتم اعتماد هذه الطريقة في Java (يستخدم Python طريقة العد المرجعية). انظر إلى الكود التالي:
الفئة العامة الرئيسية {public static void main (string [] args) {myObject Object1 = new myobject () ؛ myobject object2 = new myobject () ؛ Object1.Object = Object2 ؛ Object2.Object = Object1 ؛ Object1 = null ؛ Object2 = null ؛ }} class myobject {public object = null ؛}الجملتين الأخيرتين يعينان كائن 1 و Object2 إلى NULL ، مما يعني أن الكائنات التي أشار إليها Object1 و Object2 لم تعد متاحة ، ولكن لأنها تشير إلى بعضها البعض ، فإن عددهم المرجعي ليس 0 ، ثم لن يقوم جامع القمامة بإعادة تدويرها أبدًا.
لحل هذه المشكلة ، يتم اعتماد طريقة تحليل إمكانية الوصول في Java. الفكرة الأساسية لهذه الطريقة هي البحث من خلال سلسلة من كائنات "GC Roots" كنقطة انطلاق. إذا لم يكن هناك مسار يمكن الوصول إليه بين "جذور GC" وكائن ، يقال إن الكائن غير قابل للوصول. ومع ذلك ، تجدر الإشارة إلى أن الكائن الذي يُحكم عليه أنه لا يمكن الوصول إليه قد لا يصبح بالضرورة كائنًا قابل لإعادة التدوير. يجب أن يمر الكائن الذي يتم الحكم عليه على أنه لا يمكن الوصول إليه من خلال عمليتين على الأقل لتصبح كائنًا قابل لإعادة التدوير. إذا لم يكن هناك أي إمكانية لتصبح كائنًا قابل لإعادة التدوير خلال هاتين العمليتين للعلامة ، فسيصبح بشكل أساسي كائنًا قابل لإعادة التدوير.
بالنسبة لكيفية تشغيل طريقة تحليل إمكانية الوصول ، لم أفهمها بوضوح شديد بعد. إذا كان أي صديق أكثر وضوحًا ، فالرجاء إعطائي بعض النصائح.
دعونا نرى مثالًا أدناه:
Object aobj = new Object () ؛ Object bobj = new Object () ؛ Object cobj = new Object () ؛ aobj = bobj ؛ aobj = cobj ؛ cobj = null ؛ aobj = null ؛
أي سطر قد يجعل الكائن قابلاً لإعادة التدوير؟ سوف يتسبب الكود في السطر 7 في أن تصبح الكائنات كائنات قابلة لإعادة التدوير. أما السبب وراء ترك القراء للتفكير بأنفسهم.
دعونا نلقي نظرة على مثال آخر:
String str = new string ("Hello") ؛ softreference <string> sr = new softreference <string> (سلسلة جديدة ("Java")) ؛ PreferReference <string> wr = new Preferference <string> (سلسلة جديدة ("World") ؛أي من هذه الجمل الثلاث ستجعل كائن سلسلة قابل لإعادة التدوير؟ ستحدد الجملة 2 و 3 ، والجملة 2 كائن السلسلة ككائن قابل لإعادة التدوير عندما لا تكون هناك ذاكرة كافية ، وفي الجملة الثالثة ، سيتم تحديد كائن السلسلة ككائن قابل لإعادة التدوير في أي حال.
أخيرًا ، دعونا نلخص المواقف الشائعة التي يتم فيها الحكم على الأشياء ككائنات قابلة لإعادة التدوير التي يتم مواجهتها عادةً:
1) عرض قيمة مرجع إلى NULL أو نقطة المرجع الذي أشار بالفعل إلى كائن إلى كائن جديد ، مثل الرمز التالي:
Object obj = new Object () ؛ obj = null ؛ object obj1 = new Object () ؛ Object OBJ2 = new Object () ؛ OBJ1 = OBJ2 ؛
2) المرجع المحلي إلى الكائن المشار إليه ، مثل الكود التالي:
void fun () {...... for (int i = 0 ؛ i <10 ؛ i ++) {object obj = new Object () ؛ System.out.println (obj.getClass ()) ؛ }}في كل مرة يتم تنفيذ الحلقة ، سيصبح كائن الكائن الذي تم إنشاؤه كائنًا قابل لإعادة التدوير.
3) ترتبط المراجع الضعيفة فقط بالأشياء ، مثل:
PreferReference <string> WR = New DefenFerference <string> (سلسلة جديدة ("World")) ؛2. خوارزمية جمع القمامة النموذجية
بعد تحديد القمامة التي يمكن إعادة تدويرها ، يتعين على جامع القمامة القيام به هو بدء جمع القمامة ، ولكن هناك مشكلة واحدة تنطوي عليها: كيفية جمع القمامة بكفاءة. نظرًا لأن مواصفات الجهاز الظاهري Java لا تضع لوائح واضحة حول كيفية تنفيذ جامع القمامة ، يمكن للأجهزة الافتراضية لكل شركة تصنيع تنفيذ جامع القمامة بطرق مختلفة ، لذلك تتم مناقشة الأفكار الأساسية للعديد من خوارزميات جمع القمامة الشائعة هنا.
1. خوارزمية SWEEP (MARK-CLEAR)
هذه هي خوارزمية مجموعة القمامة الأساسية. السبب في أنه يقال إنه الأكثر أساسية هو أنه أسهل تنفيذ وأبسط فكرة. تنقسم خوارزمية إزالة العلامات إلى مرحلتين: مرحلة العلامات ومرحلة المقاصة. تتمثل مهمة مرحلة العلامات في تحديد جميع الكائنات التي تحتاج إلى إعادة تدويرها ، ومرحلة المقاصة هي إعادة تدوير المساحة التي تشغلها الكائنات المحددة. يتم عرض العملية المحددة في الشكل أدناه:
يمكن أن نرى بسهولة من الشكل أن خوارزمية إزالة العلامات أسهل في التنفيذ ، ولكن هناك مشكلة خطيرة أنه من السهل إنشاء شظايا ذاكرة. قد يتسبب الكثير من الشظايا في عدم القدرة على إيجاد مساحة كافية عند تخصيص مساحة للكائنات الكبيرة في العملية اللاحقة ، وتشغيل إجراء جديد لجمع القمامة مقدمًا.
2. نسخ (نسخ) خوارزمية
من أجل حل أوجه القصور في خوارزمية مارك-Sweep ، تم اقتراح خوارزمية النسخ. إنه يقسم الذاكرة المتاحة إلى قطعتين من الحجم المتساوي حسب السعة ، باستخدام قطعة واحدة فقط في وقت واحد. عند استخدام قطعة الذاكرة هذه لأعلى ، انسخ الكائن الذي لا يزال قائماً إلى قطعة أخرى ، ثم قم بتنظيف مساحة الذاكرة المستخدمة في وقت واحد ، حتى لا تحدث مشاكل تجزئة الذاكرة. يتم عرض العملية المحددة في الشكل أدناه:
على الرغم من أن هذه الخوارزمية سهلة التنفيذ ، فهي فعالة في التشغيل وليس من السهل إنشاء تجزئة الذاكرة ، إلا أنها مكلفة استخدام مساحة الذاكرة لأن الذاكرة التي يمكن استخدامها تقل إلى نصف الأصلي.
من الواضح أن كفاءة خوارزمية النسخ لها علاقة كبيرة بعدد الكائنات الباقية. إذا كان هناك العديد من الأشياء الباقية ، فسيتم تقليل كفاءة خوارزمية النسخ بشكل كبير.
3. خوارزمية مميزة (MARK-COLLINATE)
من أجل حل أوجه القصور في خوارزمية النسخ واستفادة كاملة من مساحة الذاكرة ، يتم اقتراح خوارزمية Mark-Compact. تمثل الخوارزمية نفس العلامة ، ولكن بعد الانتهاء من العلامة ، لا تنظف مباشرة الكائنات القابلة لإعادة التدوير ، ولكنها تنقل جميع الكائنات الحية إلى نهاية واحدة ثم تنظف الذاكرة خارج حدود النهاية. يتم عرض العملية المحددة في الشكل أدناه:
4. خوارزمية جمع الأجيال
تستخدم خوارزمية مجموعة الجيل حاليًا من قبل معظم جامعي القمامة JVM. فكرتها الأساسية هي تقسيم الذاكرة إلى عدة مناطق مختلفة وفقًا لدورة حياة بقاء الكائن. بشكل عام ، تنقسم منطقة الكومة إلى الجيل القديم والجيل الشاب. تتمثل خاصية الجيل القديم في أن هناك عددًا صغيرًا فقط من الأشياء التي يجب إعادة تدويرها في كل مرة يتم فيها جمع القمامة ، في حين أن خاصية الجيل الجديد هي أن هناك عددًا كبيرًا من الكائنات يجب إعادة تدويرها في كل مرة يتم فيها جمع القمامة. ثم يمكن اعتماد خوارزمية التجميع الأنسب وفقًا لخصائص الأجيال المختلفة.
في الوقت الحاضر ، يتبنى معظم جامعي القمامة خوارزمية النسخ للجيل الجديد ، لأنه في الجيل الجديد ، يجب إعادة تدوير معظم الأشياء في كل مرة يتم فيها جمع مجموعة القمامة ، مما يعني أن عدد العمليات التي تحتاج إلى نسخها صغيرة نسبيًا ، ولكن في الواقع ، لا يتم تقسيم مساحة الجيل الجديد وفقًا لنسبة 1: 1. بشكل عام ، ينقسم الجيل الجديد إلى مساحة أكبر عدن ومساحة أصغر من الناجين. في كل مرة يتم فيها استخدام مساحة عدن وأحد المساحات الناجية ، عند إعادة تدويرها ، يتم نسخ الكائنات التي لا تزال محققة في عدن والناجين إلى مساحة أخرى من الناجين ، ثم يتم تنظيف المساحات التي تم استخدامها للتو ومساحات الناجين التي تم استخدامها للتو.
نظرًا لأن الشيخوخة هي أنه يتم إعادة تدوير عدد صغير فقط من الكائنات في كل مرة ، يتم استخدام خوارزمية Mark-Compact بشكل عام.
لاحظ أن هناك جيلًا آخر خارج منطقة الكومة ، وهو توليد دائم ، والذي يتم استخدامه لتخزين فصول الدرجة ، والثوابت ، وأوصاف الطريقة ، وما إلى ذلك. إعادة تدوير الجيل الدائم بشكل أساسي يعيد تدوير جزأين: الثوابت المهملة والفصول الدراسية غير المجدية.
3. جامع القمامة النموذجي
خوارزمية جمع القمامة هي الأساس النظري لإعادة تدوير الذاكرة ، ومجمع القمامة هو التنفيذ المحدد لإعادة تدوير الذاكرة. فيما يلي وصف للعديد من جامعي القمامة الذي توفره الجهاز الظاهري للنقطة الساخنة (JDK 7). يمكن للمستخدمين الجمع بين جامعي المستخدمين في كل حقبة وفقًا لاحتياجاتهم الخاصة.
1. القديم/التسلسلي
جامع القديم المسلسل/التسلسلي هو جامع أساسية وأقدم. إنه جامع مؤشر ترابط واحد ويجب إيقاف جميع مؤشرات ترابط المستخدم عندما تقوم بجمع القمامة. المجمع التسلسلي هو جامع للجيل الجديد ، باستخدام خوارزمية النسخ ، والمجمع القديم التسلسلي هو جامع للجيل القديم ، باستخدام خوارزمية العلامات. ميزةها هي أنها بسيطة وفعالة ، ولكن عيوبها هي أنها ستتسبب في توقف للمستخدمين.
2.Parnew
Collector Parnew هو نسخة متعددة الخيوط من جامع التسلسل الذي يستخدم مؤشرات ترابط متعددة لجمع القمامة.
3
جامع Scavenge Parallel هو جيل جديد من هواة الجمع المتعددة (جامعي متوازيين). لا يحتاج إلى إيقاف مؤشرات ترابط المستخدم الأخرى أثناء إعادة التدوير. ويستخدم خوارزمية النسخ. يختلف هذا المجمع عن الجمعين الأولين. هو أساسا لتحقيق إنتاجية محكومة.
4
Parallel Old هو إصدار قديم من جامع Scavenge Parallel (جامع متوازي) باستخدام خوارزميات متعددة الترابطات وخوارزميات مارك.
5.cms
جامع CMS (اكتساح العلامة الحالية) هو جامع يهدف إلى الحصول على أقصر وقت توقف للاسترداد. إنه جامع متزامن يستخدم خوارزمية مارك-Sweep.
6.g1
جامع G1 هو أكثر الإنجازات المتطورة في تطوير تكنولوجيا جامع اليوم. إنه جامع للتطبيقات من جانب الخادم التي يمكن أن تستفيد بالكامل من بيئات متعددة CPU ومتعددة النواة. لذلك فهو جامع موازٍ ومتوازي ، ويمكنه بناء نموذج وقت وقفة يمكن التنبؤ به.
فيما يلي بعض الأشياء حول تخصيص الذاكرة:
في الاتجاه العام ، يتم تخصيص تخصيص الذاكرة للكائنات على الكومة. يتم تخصيص الأشياء بشكل أساسي في الجيل الجديد من مساحة عدن ومن الفضاء ، وفي حالات نادرة سيتم تخصيصها مباشرة في الشيخوخة. إذا كانت مساحة الجيل الجديد من مساحة عدن ومن المساحة غير كافية ، فسيتم بدء GC. إذا تم تنفيذ GC ، يمكن أن تستوعب مساحة Eden ومن الفضاء الكائن ويتم وضعها في مساحة عدن ومن الفضاء.
خلال عملية GC ، سيتم نقل الأشياء الباقية في Eden Space ومن الفضاء إلى الفضاء ، ثم سيتم تنظيف مساحة عدن ومن الفضاء. إذا كان لا يمكن أن يكون المساحة كافية لتخزين كائن أثناء التنظيف ، فسوف ينقل الكائن إلى الشيخوخة. بعد GC ، يتم استخدام مساحة عدن والمساحة. في المرة القادمة التي تقوم فيها GC ، سيتم نسخ الكائن الباقي من الفضاء ، وسيتم تكرار الحلقة. عندما يهرب كائن ما من GC مرة واحدة في منطقة الناجين ، سيتم زيادة عمر هدفه بمقدار 1. بشكل افتراضي ، إذا كان الكائن يبلغ من العمر 15 عامًا ، فسوف ينتقل إلى منتصف العمر من العمر.
بشكل عام ، سيتم تخصيص الأشياء الكبيرة مباشرة للشيخوخة. تشير ما يسمى الكائنات الكبيرة إلى الكائنات التي تتطلب كمية كبيرة من مساحة التخزين المستمرة. النوع الأكثر شيوعًا من الأشياء الكبيرة هو صفائف كبيرة ، مثل:
Byte [] Data = New Byte [4*1024*1024]
سيتم تخصيص هذا النوع من مساحة التخزين بشكل عام مباشرة في كبار السن.
بالطبع ، لا يتم إصلاح قواعد التخصيص بنسبة 100 ٪ ، وهو ما يعتمد على نوع مجموعة جامع القمامة والمعلمات ذات الصلة لـ JVM.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.