اقتباس FinalReference
هذا الفئة عبارة عن نوع حزمة ، يشير إلى أنه ليس جزءًا عامًا ويرث من المرجع ، مما يعني أنه أيضًا نوع مرجعي محدد. لذلك ، قبل إعادة تدوير كل كائن فيه ، سيتم وضعه في arendQyebcequeue المحدد.
يستخدم هذا الكائن المرجعي خصيصًا للفئة مع الأساليب اللمسات الأخيرة. يمكن فهم أن كل كائن ذو طرق المقابلة سيتم تغليفه ككائن FinalRefernece.
نظرًا لأن طريقة الانتهاء محددة بواسطة الكائن ، فإن تنفيذها الافتراضي فارغ. ثم إذا تم إعادة كتابة هذه الطريقة ، فلن يكون الجسم بالتأكيد فارغًا. هذا الاختلاف يمكن أن يحدث من خلال هذا. طالما أن طريقة الانتهاء تنفذ فئة غير فارغة ، يجب تسجيل الكائنات التي تم إنشاؤها في FinalRefernece.
يمكن تسجيل هذه الخطوة وفقًا لذلك عن طريق استدعاء طريقة مُنشئ الكائن الافتراضي أثناء NewInstance.
طريقة التسجيل النهائية#
عندما تسمى هذه الطريقة بشكل أساسي ، سيتم إنشاء كائن Finalizer المقابل ، ويرث كائن Finalizer من FinalReference. تم الإعلان عن هذه الطريقة على النحو التالي:
/ * تم استدعاؤه بواسطة VM */static void Register (Object Finalizee) {New Finalizer (Finalizee) ؛} كما يتضح من التعليقات أعلاه ، سيتم استدعاء هذه الطريقة بواسطة JVM في فترة محددة.
ثم قم بالتبديل إلى مُنشئ Finalizer ، كما هو موضح أدناه:
Private Finalizer (Object Finalizee) {Super (Finalizee ، Queue) ؛ يضيف()؛} يمكن ملاحظة أنه سيتم استدعاء الكائن المرجعي المقابل مرة أخرى من خلال قائمة الانتظار. تتمثل وظيفة الإضافة في حفظ جميع الكائنات التي لم تضع اللمسات الأخيرة على الطريقة وتسميتها في System.shutdown النهائي. shutdown. قم بتعيينه من خلال Runtime#runFinalizersOnExit .
مرجع
سيتم وضع قائمة الانتظار المرجعية هذه في قائمة الانتظار هذه قبل إعادة تدوير الكائنات الداخلية للكائن المرجعي المقابل (سيتم شرح الوصف التفصيلي في مقالة أخرى حول المرجع.) ، لأنه يجب الحصول على الكائن المقابل فقط من قائمة الانتظار هذه ، فإن هذا الكائن جاهز بالتأكيد لإعادة تدويره.
ثم استدعاء طريقة الانتهاء المقابلة قبل إعادة التدوير.
موضوع نهائي
يستمر هذا الموضوع في الحصول على بيانات من قائمة الانتظار ، ثم يستدعي طريقة اللمسات الأخيرة المقابلة. الرمز المقابل كما يلي:
لـ (؛؛) {try {finalizer f = (finalizer) queue.remove () ؛ f.runfinalizer (JLA) ؛ } catch (InterruptedException X) {// تجاهل ومتابعة}}}إن Runfinalizer المقابل هو كما يلي:
متزامن (هذا) {if (hasbeenfinalized ()) return ؛ remove () ؛} جرب {object finize = this.get () ؛ if (finalizee! = null &&! (finalizee مثيل java.lang.enum)) {jla.invokefinalize (finalizee) ؛ ! }} catch (throwable x) {} super.clear () ؛في المنطق أعلاه ، قم بإزالة الاتصال أولاً وإزالته من النهاية. تتمثل هذه الطريقة في التأكد من أن الانتهاء من كل كائن لن يتم استدعاؤه إلا مرة واحدة على الأكثر ، أي أن المكالمة الحالية قد اكتملت. سيتم تسجيله في الحالة المقابلة ، أي عوائد Hasbeenfingized True (في الواقع ، فهذا يعني أن يشير إلى المؤشر التالي إلى نفسه. أي أنه لم يتم الانتهاء منه أبدًا ، وليس هناك حاجة للاتصال بالانتهاء مرة أخرى).
التالي هو استدعاء طريقة الانتهاء المقابلة. jla.invokeFinalize أعلاه هو في الواقع استدعاء طريقة الانتهاء من الكائن المقابل. في هذه العملية ، يتم الحصول على الكائن الأصلي لأول مرة من خلال GET. في عملية JVM بأكملها ، لم يتم ضبط المرجع على NULL قبل إعادة التدوير لتنظيم Finalizereference. لأنه هنا ، يمكن دائمًا الحصول على الكائن المرجعي المقابل.
بعد المعالجة ، يتم استدعاء وضوح المقابل أخيرًا لمسح المرجع المقابل. هذا يحقق تأثير المرجع النهائي لا يوجد أي كائن آخر للإشارة إليه.
في المعالجة أعلاه ، لا يوجد حد في وقت الاتصال. لذلك ، بمجرد استدعاء الانتهاء من الكائن ببطء ، سيؤثر ذلك على تنفيذ سلسلة إعادة التدوير بأكملها ، وسيتم إنشاء استثناء من OOM المقابل. لذلك ، ما لم تكن في الحالات الخاصة ، لا تعيد كتابة اللمسات الأخيرة. يجب أن تكون هناك طرق أخرى للتعامل مع السيناريوهات المقابلة. على سبيل المثال ، Finalizablereference في الجوافة.
يبدأ Finalizer الخيط
في الخيط أعلاه ، سيتم بدء تشغيله أثناء بدء تشغيل العملية المقابلة. يمكن أن يُفهم أن الكائن يؤدي إلى تهيئة فئة Finalizer عن طريق استدعاء register(object) . بعد ذلك ، في كتلة التهيئة الثابتة ، سيتم بدء تشغيل مؤشر ترابط إعادة التدوير المقابل. رمز التهيئة المقابل كما يلي:
ثابت {threadgroup tg = thread.currentThRead (). getThReadGroup () ؛ لـ (threadgroup tgn = tg ؛ tgn! = null ؛ tg = tgn ، tgn = tg.getParent ()) ؛ Thread Finalizer = New FinalizerThread (TG) ؛ Finalizer.setPriority (thread.max_priority - 2) ؛ Finalizer.setdaemon (صواب) ؛ Finalizer.start () ؛}الثابت أعلاه هو كتلة تهيئة ثابتة ، أي ، طالما يتم استخدام المزروع النهائي للفصل ، سيتم تشغيل المكالمة المقابلة. مجموعة مؤشرات الترابط المستخدمة هنا هي مجموعة مؤشرات ترابط النظام ، ولا تزال الأولوية عالية نسبيًا ، ويتم تكوينها كخيط خلفية.
عند استخدام JSTACK لطباعة المواضيع ، يتم تشغيل مؤشرات الترابط الموضحة أدناه الشكل هنا. كما هو مبين في الشكل أدناه
لخص
يعمل Finalizer بأكمله معًا من خلال FinalReference بواسطة JVM وفئات Java المقابلة. لا يتم تنفيذها جميعًا بواسطة JVM ، لذلك يمكن اعتبارها أنها ليست أساسية للغاية ، ولكن لتنفيذ الدلالات المقابلة. يتم كل شيء بواسطة Java العادي وتعاون بواسطة JVM. يعد فهم العملية برمتها أيضًا فهمًا لآلية الجولة في Java نفسها.