[java] هل استخدام النهائي للمتغيرات في جافا تحسين جمع القمامة؟



Answers

إن إعلان final متغير محلي لن يؤثر على تجميع البيانات المهملة ، فهذا يعني أنه لا يمكنك تعديل المتغير. يجب أن لا يتم ترجمة المثال أعلاه لأنك تقوم بتعديل متغير totalWeight والذي تم وضع علامة عليه final . من ناحية أخرى ، فإن الإعلان عن final ( double بدلاً من Double ) سيسمح بإدراج هذا المتغير في شفرة الاتصال ، بحيث يمكن أن يسبب بعض الذاكرة وتحسين الأداء. يتم استخدام هذا عندما يكون لديك عدد من public static final Strings في الفصل.

بشكل عام ، سيقوم المترجم ووقت التشغيل بتحسين المكان الذي يمكن فيه ذلك. من الأفضل كتابة التعليمات البرمجية بشكل مناسب وعدم محاولة أن تكون خادعة للغاية. استخدم final عندما لا تريد تعديل المتغير. بفرض أن أي تحسينات سهلة سيتم تنفيذها بواسطة المحول البرمجي ، وإذا كنت قلقًا بشأن الأداء أو استخدام الذاكرة ، استخدم أداة تعريف لتحديد المشكلة الحقيقية.

Question

اليوم أنا وزملائي لديهم مناقشة حول استخدام الكلمة الأساسية final في Java لتحسين مجموعة البيانات المهملة.

على سبيل المثال ، إذا كتبت طريقة مثل:

public Double doCalc(final Double value)
{
   final Double maxWeight = 1000.0;
   final Double totalWeight = maxWeight * value;
   return totalWeight;  
}

إن إعلان المتغيرات في الطريقة final سيساعد جمع البيانات المهملة على تنظيف الذاكرة من المتغيرات غير المستخدمة في الطريقة بعد خروج الطريقة.

هل هذا صحيح؟




بعض النقاط لتوضيح:

  • يجب أن لا يؤدي إلغاء المرجع إلى مساعدة GC. إذا حدث ذلك ، فسيشير إلى أن المتغيرات الخاصة بك قد تم تحديد حجمها. استثناء واحد هو حالة محسوبية الكائن.

  • لا يوجد تخصيص مكدس حتى الآن في Java.

  • التصريح عن متغير نهائي يعني أنك لا تستطيع (في الظروف العادية) تعيين قيمة جديدة لهذا المتغير. بما أن النهائي لا يذكر شيئًا عن النطاق ، فهو لا يقول أي شيء عن تأثيره على GC.




يبدو أن هناك الكثير من الإجابات التي هي تخمينات متجولة. والحقيقة هي أنه لا يوجد معدّل نهائي للمتغيرات المحلية في المستوى البايت. لن تعرف الآلة الافتراضية أبداً أن المتغيرات المحلية الخاصة بك تم تعريفها على أنها نهائية أو لا.

الجواب على سؤالك هو لا.




الوقت الوحيد الذي أفضّل فيه إعلان المتغيرات المحلية كنهائي هو عندما:

  • لا بد لي من جعلها نهائية بحيث يمكن مشاركتها مع بعض فئة مجهولة (على سبيل المثال: إنشاء موضوع الخفي والسماح لها الوصول إلى بعض القيمة من إرفاق طريقة)

  • أريد أن أجعلها نهائية (على سبيل المثال: بعض القيمة التي لا يجب أن يتم تجاوزها عن طريق الخطأ)

هل يساعدون في جمع القمامة سريع؟
يصبح AFAIK كائنًا مرشحًا لمجموعة GC إذا كان يحتوي على إشارات قوية إلى الصفر وفي هذه الحالة أيضًا لا يوجد ضمان بأنه سيتم جمع القمامة فورًا. بشكل عام ، يقال أن الإشارة القوية تموت عندما تخرج من النطاق أو يقوم المستخدم بإعادة تخصيصها بشكل صريح إلى مرجع فارغ ، وبالتالي ، يعني الإعلان عنها نهائيًا أن الإشارة ستظل موجودة حتى يتم العثور على الطريقة (ما لم يتم تضييق نطاقها صراحةً إلى كتلة داخلية محددة {}) لأنه لا يمكنك إعادة تعيين المتغيرات النهائية. ﻟذﻟك أﻋﺗﻘد أن "ﻣﺟﻣوﻋﺔ اﻟﻘﻣﺎﻣﺔ" اﻟﻧﮭﺎﺋﯾﺔ ﻗد ﺗدﺧل ﺗﺄﺧﯾر ﻣﺣﺗﻣل ﻏﯾر ﻣرﻏوب ﻓﯾﮫ.




لا يمكن تغيير المتغيرات النهائية بعد التعيين الأولي (يتم فرضه بواسطة المترجم).

هذا لا يغير سلوك مجموعة البيانات المهملة على هذا النحو. الشيء الوحيد هو أن هذه المتغيرات لا يمكن إبطالها عندما لا يتم استخدامها أكثر من ذلك (مما قد يساعد في جمع القمامة في مواقف ضيقة الذاكرة).

يجب أن تعلم أن النهائي يسمح للمترجم بعمل افتراضات حول ما يجب تحسينه. تضمين رمز ولا يتضمن رمزًا معروفًا لا يمكن الوصول إليه.

final boolean debug = false;

......

if (debug) {
  System.out.println("DEBUG INFO!");
}

لن يتم تضمين println في رمز البايت.




هناك حالة ركن غير معروفة جيدا مع جامعي القمامة الأجيال. (للحصول على وصف مختصر ، اقرأ إجابة benjismith للحصول على رؤية أعمق ، اقرأ المقالات في النهاية).

الفكرة في GCs الأجيال هي أن معظم الأجيال الصغيرة فقط تحتاج إلى النظر فيها. يتم فحص موقع الجذر للمراجع ، ثم يتم فحص كائنات الجيل الشاب. خلال هذا الاحتلالات الأكثر تكرارا يتم فحص أي كائن في الجيل القديم.

الآن ، المشكلة تأتي من حقيقة أنه لا يُسمح لأحد الكائنات بالإشارة إلى الأشياء الأصغر. عندما يحصل كائن طويل العمر (الجيل القديم) على مرجع إلى كائن جديد ، يجب تتبع هذا المرجع بشكل صريح من قِبل أداة تجميع البيانات المهملة (راجع المقال من IBM على أداة تجميع JVM ذات النقاط الفعالة ) ، مما يؤثر فعليًا على أداء GC.

السبب في عدم قدرة كائن قديم على الإشارة إلى شخص أصغر هو أنه ، نظرًا لعدم تحديد الكائن القديم في مجموعات صغيرة ، إذا تم الاحتفاظ بالإشارة الوحيدة إلى الكائن في الكائن القديم ، فلن يتم وضع علامة عليه ، وسيكون خطأ deallocated خلال مرحلة الاجتياح.

بالطبع ، كما أشار العديد ، الكلمة الأساسية الأخيرة لا يؤثر حتمًا على مجمّع البيانات المهملة ، ولكنه يضمن عدم تغيير المرجع إلى كائن أصغر سناً إذا نجا هذا الكائن من المجموعات الثانوية وجعله في الكومة القديمة.

مقالات:

IBM على جمع القمامة: history ، في نقطة ساخنة JVM performance . قد لا تكون هذه المعلومات صالحة تمامًا ، نظرًا لأنها تعود إلى عام 2003/2004 ، ولكنها تقدم بعضًا من السهل قراءة النظرات إلى GCs.

الشمس على ضبط جمع القمامة




الشيء الوحيد الذي يمكنني التفكير فيه هو أن المترجم قد يحسن المتغيرات النهائية ويضمنها كثوابت في الشفرة ، وبالتالي ينتهي الأمر بعدم تخصيص أي ذاكرة.




Related