1 نظرة عامة
من المعروف أن Java تدعم المنصة اللاأدرية والأمن وحركية الشبكة. يتكون منصة Java من Java Virtual Machines و Java Core Classes ، والتي توفر واجهة برمجة موحدة لبرامج Java النقية ، بغض النظر عن نظام التشغيل المنخفض. ويرجع ذلك بالتحديد إلى الجهاز الظاهري Java ، حيث يمكن ضمان ادعاءها بأنها "تم تجميعها مرة واحدة ، وتشغيلها في كل مكان".
1.1 عملية تنفيذ برنامج Java
يعتمد تنفيذ برامج Java على بيئة التجميع والبيئة الجارية. يتم تحويل الرمز المصدر إلى رمز الجهاز القابل للتنفيذ ، والذي يتم الانتهاء منه من خلال العملية التالية:
جوهر تقنية Java هو الجهاز الظاهري Java ، لأن جميع برامج Java تعمل على الجهاز الظاهري. يتطلب تشغيل برامج Java تعاون Java Virtual Machine و Java API و Java Class. مثيل الجهاز الافتراضي Java مسؤول عن تشغيل برنامج Java. عند بدء تشغيل برنامج Java ، يولد مثيل الجهاز الظاهري. عندما ينتهي البرنامج ، يموت مثيل الجهاز الظاهري.
ميزة Java عبر المنصات هي أنها تحتوي على أجهزة افتراضية تستهدف منصات مختلفة.
1.2 جافا الجهاز الظاهري
تتمثل المهمة الرئيسية لجهاز Java Virtual في تحميل ملفات الفئة وتنفيذ Bytecodes فيها. كما يتضح من الشكل أدناه ، يحتوي جهاز Java Virtual على محمل فئة ، والذي يمكنه تحميل ملفات الفئة من البرامج وواجهة برمجة التطبيقات. سيتم تحميل الفئات المطلوبة لتنفيذ البرنامج فقط في Java API ، ويتم تنفيذ رمز Bytecode بواسطة محرك التنفيذ.
عندما يتم تنفيذ جهاز Java الظاهري بواسطة برنامج على نظام التشغيل المضيف ، يتفاعل برنامج Java مع المضيف من خلال استدعاء الأساليب المحلية. تتم كتابة أساليب Java بلغة Java ، تم تجميعها في Bytecode ، وتخزينها في ملفات الفصل. تتم كتابة الطريقة المحلية بلغة C/C ++/التجميع ، والتي تم تجميعها في رمز الجهاز المتعلق بالمعالج ، المخزنة في مكتبة الارتباط الديناميكي ، والتنسيق ملكية لكل منصة. وبالتالي فإن الطريقة المحلية هي توصيل برامج Java بنظام التشغيل المضيف الأساسي.
نظرًا لأن جهاز Java Virtual لا يعرف كيف تم إنشاء ملف فئة وما إذا كان يتم العبث به ، فإنه ينفذ كاشف ملف الفئة للتأكد من استخدام الأنواع المحددة في ملف الفصل بأمان. يضمن مدقق ملف الفصل الدرس متانة البرنامج من خلال أربعة عمليات مسح مستقلة:
・ مجموعة ملف الفئة
・ فحص دلالي من بيانات النوع
bytecode التحقق
・ التحقق من المرجع الرمز
عند تنفيذ رمز Bytecode ، تؤدي أجهزة Java الافتراضية أيضًا آليات أمان مضمنة أخرى. إنها خصائص ضمان متانة برامج Java كلغات برمجة Java ، وهي أيضًا خصائص الأجهزة الافتراضية Java:
・ تحويل مرجعي آمن من النوع
・ الوصول إلى الذاكرة المنظمة
・ جمع القمامة التلقائي
・ فحص حدود الصفيف
・ اقتباس فارغ فحص
1.3 نوع بيانات الجهاز الافتراضي Java
تؤدي الأجهزة الافتراضية Java الحسابات من خلال أنواع معينة من البيانات. يمكن تقسيم أنواع البيانات إلى نوعين: الأنواع الأساسية وأنواع المراجع ، كما هو موضح في الشكل أدناه:
لكن منطقية مميزة بعض الشيء. عندما يقوم المترجم بتجميع رمز مصدر Java في Bytecode ، فإنه سيمثل Boolean مع int أو byte. في الأجهزة الافتراضية Java ، يتم تمثيل False بـ 0 ، ويمثل True جميع الأعداد الصحيحة غير الصفر. مثل لغة Java ، يكون نطاق القيمة للنوع الأساسي لجهاز Java Virtual متسقًا في كل مكان ، بغض النظر عن ماهية النظام الأساسي المضيف ، يعد طويلًا دائمًا عدد صحيح موقّع مع مكمل 64 بت في أي جهاز افتراضي.
بالنسبة إلى ReturnadDress ، يتم استخدام هذا النوع الأساسي لتنفيذ البند الأخير في برنامج Java. لا يمكن لمبرمجي Java استخدام هذا النوع ، وتشير قيمته إلى رمز opcode لتعليم الجهاز الظاهري.
2 البنية
في مواصفات الجهاز الظاهري Java ، يتم وصف سلوك مثيل الجهاز الظاهري من حيث النظام الفرعي ، ومنطقة الذاكرة ، ونوع البيانات ، والتعليمات ، ويظهر هذه المكونات معًا البنية الداخلية المجردة للآلة الافتراضية.
ملف 2.1Class
يحتوي ملف JavacLass على جميع المعلومات حول فئة أو واجهة. "النوع الأساسي" لملف الفصل هو كما يلي:
| U1 | 1 بايت ، نوع غير موقّع |
| U2 | 2 بايت ، نوع غير موقّع |
| U4 | 4 بايت ، نوع غير موقّع |
| U8 | 8 بايت ، نوع غير موقّع |
إذا كنت تريد معرفة المزيد ، فإن JVM SE7 من Oracle يعطي المواصفات الرسمية: مواصفات الجهاز الظاهري Java®
محتويات ملف الفصل:
classfile {u4 magic ؛ // الرقم السحري: 0xcafebabe ، يستخدم لتحديد ما إذا كان ملف فئة Java U2 Minor_version ؛ // رقم إصدار صغير U2 major_version ؛ // رقم الإصدار الرئيسي u2 stater_pool_count ؛ // حجم المسبح الثابت CP_INFO CONSTONT_POOL [CONSTONT_POOL_COUNT-1] ؛ // حمام سباحة ثابت U2 Access_Flags ؛ // أعلام الوصول في فئة ومستويات الواجهة (تم الحصول عليها من خلال | التشغيل) u2 this_class ؛ // فئة الفئة (تشير إلى ثوابت الفصل في تجمع ثابت) U2 Super_Class ؛ // مؤشر الفئة الحالي (يشير إلى ثوابت الفصل في تجمع ثابت) u2 interfaces_count ؛ // interfaces index index interfaces [interfaces_count] ؛ // Interface Index Set U2 Fields_Count ؛ // count count counte field_info fields [fields_count] ؛ // Field Table Set U2 Methods_Count ؛ // COUNT COUNT COUNT METHORM_INFO طرق [MOTES_COUNT] ؛ // طريقة جدول تعيين u2 attributes_count ؛ // عدد سمات السمة attribute_info [attributes_count] ؛ // جدول السمة} 2.2 نظام محمل فئة
النظام الفرعي لوادر الفئة مسؤول عن العثور على معلومات نوع وتحميلها. في الواقع ، هناك نوعان من المحمولين للأجهزة الافتراضية Java: لوادر النظام والوادر المعرفة من قبل المستخدم. السابق هو جزء من تنفيذ الجهاز الافتراضي Java ، في حين أن الأخير هو جزء من برنامج Java.
・ BootstrapClassloader: يتم استخدامه لتحميل المكتبة الأساسية لـ Java ، التي تم تنفيذها في الكود الأصلي ، ولا يتم موروثها من java.lang.classloader.
・ ExtensionClassloader: يتم استخدامه لتحميل مكتبات تمديد Java. سيوفر تطبيق الجهاز الظاهري Java دليل مكتبة تمديد. يبحث هذا المحمل الفئة عن فئات Java ويحملها في هذا الدليل.
・ تحميل فئة التطبيق: يقوم بتحميل فئات Java وفقًا لـ ClassPath of Java Application (ClassPath). بشكل عام ، يتم تحميل فئات تطبيق Java به. يمكن الحصول عليها من خلال classloader.getSystemClassLoader ().
بالإضافة إلى اللوادر الفئة التي يوفرها النظام ، يمكن للمطورين تنفيذ اللوادر الخاصة بهم من خلال ورث فئة java.lang.classloader لتلبية بعض الاحتياجات الخاصة.
يتضمن النظام الفرعي لوادر الفئة عدة مكونات أخرى من الجهاز الافتراضي Java والفئات من مكتبة Java.lang. توفر الطريقة المحددة بواسطة ClassLoader واجهة للبرنامج للوصول إلى آلية تحميل الفئة. بالإضافة إلى ذلك ، لكل نوع يتم تحميله ، يقوم جهاز Java Virtual بإنشاء مثيل لفئة Java.lang.class لتمثيل النوع. مثل الكائنات الأخرى ، يتم وضع محمل فئة محددة من قبل المستخدم ومثيلات الفصل في منطقة الكومة في الذاكرة ، بينما توجد معلومات النوع المحملة في منطقة الطريقة.
بالإضافة إلى تحديد موقع ملفات الفئة الثنائية واستيرادها ، يجب أن يكون النظام الفرعي لوادر الفئة مسؤولاً أيضًا عن التحقق من صحة الفئة المستوردة ، وتخصيص وتهيئة الذاكرة لمتغيرات الفئة ، وتوحل المراجع الرمزية. يجب أيضًا تنفيذ هذه الإجراءات بالترتيب التالي:
・ التحميل (البحث وتحميل البيانات الثنائية من النوع)
・ الاتصال (التحقق من التنفيذ: تأكد من صحة النوع المستورد ؛ التحضير: تخصيص الذاكرة لمتغيرات الفئة وتهيئتها إلى القيم الافتراضية ؛ التحليل: تحويل المراجع الرمزية في النوع إلى مراجع مباشرة)
・ التهيئة (تتم تهيئة متغيرات الفئة إلى القيمة الأولية الصحيحة)
2.3 منطقة الطريقة
في جهاز Java الظاهري ، يتم تخزين معلومات حول النوع المحمّل في الذاكرة في منطقة الطريقة. عندما يقوم جهاز افتراضي بتحميل نوع معين ، فإنه يستخدم محمل فئة لتحديد موقع ملف الفئة المقابل ، ثم يقرأ ملف الفئة ونقله إلى الجهاز الظاهري. ثم يستخرج الجهاز الظاهري معلومات النوع الموجودة فيه ويخزن هذه المعلومات في منطقة الطريقة. يمكن أيضًا جمع مناطق الطريقة بواسطة جامع القمامة ، لأن الجهاز الظاهري يسمح بالتمديد الديناميكي لبرامج JAVA من خلال لوادر فئة محددة من قبل المستخدم.
يتم تخزين المعلومات التالية في منطقة الطريقة:
・ هذا النوع من الاسم المؤهل بالكامل (مثل الاسم المؤهل تمامًا java.lang.object)
・ الاسم المؤهل بالكامل لهذا النوع من الفئة الفائقة المباشرة
・ هل نوع فئة النوع أو نوع الواجهة
・ هذا النوع من معدل الوصول (مجموعة فرعية من الجمهور ، الملخص ، النهائي)
・ قائمة مصنفة بالأسماء المؤهلة تمامًا لأي فرط فصح مباشر
・ مجموعة ثابتة من هذا النوع (مجموعة مرتبة بما في ذلك الثوابت المباشرة [سلسلة ، عدد صحيح وذوثرات Floating Point
・ معلومات الحقل (اسم الحقل ، النوع ، المعدل)
・ معلومات الطريقة (اسم الطريقة ، نوع الإرجاع ، عدد المعلمات والنوع ، المعدل)
・ جميع المتغيرات (ثابتة) باستثناء الثوابت
・ الإشارة إلى فئة ClassLoader (عند تحميل كل نوع ، يجب أن يتتبع الجهاز الظاهري ما إذا كان يتم تحميله بواسطة محمل فئة بدء التشغيل أو محمل الفئة المعرفة من قبل المستخدم)
・ الإشارة إلى فئة الفئة (لكل نوع يتم تحميله ، سيقوم الجهاز الظاهري بإنشاء مثيل لفئة java.lang.class وفقًا لذلك. على سبيل المثال ، إذا كان لديك مرجع إلى كائن java.lang.integer ، فأنت بحاجة فقط إلى استدعاء طريقة getClass () المشار إليها بواسطة كائن Integer للحصول على كائن الفئة الذي يمثل جافا.
2.4 كومة
يتم وضع جميع مثيلات الفصل أو المصفوفات التي تم إنشاؤها بواسطة برامج Java في وقت التشغيل (المصفوفات هي كائن حقيقي في جهاز Virtual Java) في نفس الكومة. نظرًا لأن مثيلات الجهاز الظاهري Java تحتوي على مساحة واحدة فقط ، فستشارك جميع المواضيع هذه الكومة. تجدر الإشارة إلى أن الجهاز الظاهري Java لديه تعليمات لتخصيص كائنات في الكومة ، ولكن ليس لديها تعليمات لتحرير الذاكرة ، لأن الجهاز الظاهري الذي تم تسليمه على هذه المهمة إلى جامع القمامة للمعالجة. لا تقوم مواصفات الجهاز الظاهري Java بفرض جامعي القمامة ، بل يتطلب فقط أن تقوم تطبيقات الماكينة الافتراضية بإدارة مساحة الكومة الخاصة بها "بطريقة ما". على سبيل المثال ، قد يكون للتنفيذ مساحة كومة ثابتة فقط. عندما يتم ملء المساحة ، فإنه يرمي ببساطة استثناء OutofMemory ، والذي لا يعتبر مسألة إعادة تدوير كائنات القمامة ، ولكنها تتوافق مع المواصفات.
لا تحدد مواصفات الجهاز الظاهري Java كيفية تمثيل كائنات Java في الكومة ، مما يمنح تطبيق قرارات الجهاز الظاهري حول كيفية التصميم. تصميم كومة محتمل على النحو التالي:
تجمع المقبض ، حمام سباحة للكائنات. مرجع الكائن هو مؤشر محلي لمسبح المقبض. فوائد هذا التصميم تفضي إلى فرز شظايا الكومة. عند تحريك الكائنات في تجمع الكائن ، يحتاج جزء المقبض فقط إلى تغيير العنوان الجديد للمؤشر يشير إلى الكائن. العيب هو أنه في كل مرة يتم فيها الوصول إلى متغير مثيل لكائن ، يجب تمريره من خلال مؤشرين.
2.5 java stack
عند بدء تشغيل الخيط ، يخصص جهاز Java Virtual مكدس Java له. يتكون مكدس Java من العديد من إطارات المكدس ، ويحتوي إطار مكدس واحد على حالة استدعاء طريقة Java. عندما يقوم مؤشر ترابط باستدعاء طريقة Java ، يدفع الجهاز الظاهري إطار مكدس جديد إلى مكدس Java الخاص بالمعلومات. عند إرجاع الطريقة ، يبرز إطار المكدس من مكدس Java. يخزن مكدس Java حالة مكالمات طريقة Java في مؤشرات الترابط - بما في ذلك المتغيرات المحلية والمعلمات وقيم الإرجاع والنتائج المتوسطة للعمليات ، إلخ. السبب في هذا التصميم هو الحفاظ على مجموعة التعليمات الخاصة بجهاز Java Virtual مضغوطًا قدر الإمكان ، وكذلك تسهيل تنفيذ الجهاز الظاهري Java على منصة مع عدد قليل من السجلات العامة. بالإضافة إلى ذلك ، تساعد الهندسة المعمارية المستندة إلى المكدس أيضًا على تحسين رمز المترجمين الديناميكيين والمترجمين الفوريين التي تنفذها بعض الأجهزة الافتراضية أثناء وقت التشغيل.
2.5.1 إطار المكدس
يتكون إطار المكدس من منطقة متغيرة محلية ومكدس معامل ومنطقة بيانات الإطار. عندما يستدعي جهاز افتراضي طريقة Java ، فإنه يحصل على مساحة متغيرة محلية وحجم مكدس المعامل لهذه الطريقة من نوع معلومات الفئة المقابلة ، ويخصص ذاكرة إطار المكدس وفقًا لذلك ، ثم يدفعها إلى مكدس Java.
2.5.1.1 منطقة المتغير المحلي
يتم تنظيم المنطقة المتغيرة المحلية في صفيف يتم حسابه من 0 بوحدات طول الكلمة. تستخدم تعليمات Bytecode البيانات الموجودة فيه من خلال فهرس يبدأ من 0. قيم الأنواع int ، تعويم ، المرجع والعائد ، تشغل عنصرًا واحدًا في الصفيف ، في حين يتم تحويل قيم الأنواع البايت ، القصيرة والشار إلى قيم int قبل تخزينها في الصفيف ، وتشغل أيضًا عنصرًا واحدًا. لكن قيم الأنواع الطويلة والمزدوجة تشغل فترتين متتاليتين في الصفيف.
2.5.1.2 OPERAND Stack
مثل المنطقة المتغيرة المحلية ، يتم تنظيم مكدس المعامل أيضًا في صفيف بطول الكلمة. إنه يصل إلى مكدس المكدس القياسي وتكديس. نظرًا لأنه لا يمكن الوصول إلى عداد البرنامج مباشرةً من خلال تعليمات البرنامج ، فإن تعليمات الجهاز الظاهري Java تحصل على معاملات من مكدس المعامل ، لذلك تعتمد تشغيله على المكدس بدلاً من السجلات. يأخذ الجهاز الظاهري مكدس المعامل كمساحة عمل له ، لأن معظم الإرشادات يجب أن تظهر البيانات من هنا ، وإجراء العمليات ، ثم دفع النتيجة مرة أخرى إلى مكدس المعامل.
2.5.1.3 منطقة بيانات الإطار
بالإضافة إلى المنطقة المتغيرة المحلية ومكدس المعامل ، تحتاج إطارات مكدس Java أيضًا إلى مناطق بيانات الإطار لدعم تحليل تجمع ثابت ، وإرجاع الطريقة العادية ، وآليات إرسال الاستثناء. عندما يريد جهاز افتراضي تنفيذ تعليمات تتطلب بيانات حمام سباحة ثابتة ، فإنها تصل إليها من خلال مؤشر إلى تجمع ثابت في منطقة بيانات الإطار. بالإضافة إلى تحليل التجمعات الثابتة ، تساعد منطقة بيانات الإطار أيضًا الجهاز الظاهري على التعامل مع الطرف العادي أو الإجهاض غير الطبيعي لطرق Java. إذا انتهى العائد بشكل طبيعي ، فيجب على الجهاز الظاهري استعادة إطار المكدس للطريقة التي تبدأ المكالمة ، بما في ذلك تعيين عداد البرنامج للإشارة إلى التعليمات التالية التي تبدأ طريقة الاتصال ؛ إذا كانت الطريقة لها قيمة إرجاع ، فيجب أن يدفع الجهاز الظاهري إلى المكدس المعامل للطريقة التي تبدأ المكالمة. للتعامل مع مخارج الاستثناء أثناء تنفيذ طريقة Java ، تحتوي منطقة بيانات الإطار أيضًا على إشارة إلى جدول الاستثناء لهذه الطريقة.
2.6 عداد البرنامج
لبرنامج Java قيد التشغيل ، يحتوي كل موضوع على عداد البرنامج. وتسمى عدادات البرنامج أيضا سجلات الكمبيوتر. يمكن لعداد البرنامج عقد مؤشر محلي و Returnaddress. عندما ينفذ مؤشر ترابط طريقة Java ، تكون قيمة عداد البرنامج دائمًا عنوان التعليمات التالية التي تم تنفيذها. يمكن أن يكون العنوان هنا مؤشرًا محليًا أو إزاحة في الطريقة Bytecode بالنسبة إلى تعليمات بدء الطريقة. إذا كان الخيط ينفذ طريقة محلية ، فإن قيمة عداد البرنامج "غير محددة".
2.7 كومة الطريقة المحلية
ستستخدم أي واجهة طريقة محلية نوعًا من مكدس الطريقة المحلية. عندما يقوم مؤشر ترابط باستدعاء طريقة Java ، يقوم الجهاز الظاهري بإنشاء إطار مكدس جديد ويدفعه إلى مكدس Java. عندما يستدعي طريقة محلية ، يحافظ الجهاز الظاهري على مكدس Java دون تغيير ولم يعد يدفع إلى المكدس الجديد في مكدس Java المترابط. يتصل الجهاز الظاهري ببساطة بشكل ديناميكي ويتصل مباشرة بالطريقة المحلية المحددة.
تتم مشاركة منطقة الطريقة والكومة من قبل جميع مؤشرات الترابط في مثيل الجهاز الظاهري. عندما يقوم الجهاز الظاهري بتحميل ملف فئة ، فإنه يوسع معلومات النوع من البيانات الثنائية الواردة في ملف الفئة ، ثم يضع معلومات النوع في منطقة الطريقة. عند تشغيل البرنامج ، يضع الجهاز الظاهري جميع الكائنات التي تم إنشاؤها بواسطة البرنامج في وقت التشغيل في الكومة.
مثل مناطق ذاكرة وقت التشغيل الأخرى ، يمكن توسيع أو تقلص منطقة الذاكرة التي تشغلها مكدس الطريقة المحلية ديناميكيًا حسب الحاجة.
3 محرك التنفيذ
في مواصفات الجهاز الظاهري Java ، يتم تعريف سلوك محرك التنفيذ باستخدام مجموعات التعليمات. سيقرر المصمم الذي ينفذ محرك التنفيذ كيفية تنفيذ رمز Bytecode ، أو يمكن تفسير التنفيذ أو تجميعها أثناء الطيران أو تنفيذها مباشرة باستخدام تعليمات على الشريحة ، أو مزيج منها.
يمكن فهم محرك التنفيذ على أنه مواصفات مجردة أو تطبيق ملموس أو مثيل تشغيل. تستخدم المواصفات التجريدية مجموعات التعليمات لتحديد سلوك محرك التنفيذ. قد يستخدم تطبيق معين مجموعة متنوعة من التقنيات المختلفة - بما في ذلك البرامج أو الأجهزة أو مجموعة من تقنية الأشجار. محرك التنفيذ كمثيل وقت التشغيل هو مؤشر ترابط.
كل مؤشر ترابط لبرنامج Java قيد التشغيل هو مثيل لمحرك تنفيذ الجهاز الظاهري المستقل. من البداية إلى نهاية دورة حياة الخيط ، يتم تنفيذ رمز Bytode أو تنفيذ طريقة محلية.
3.1 مجموعة التعليمات
يتكون دفق Bytecode للطريقة من سلسلة من الإرشادات من جهاز Java الظاهري. تحتوي كل تعليمات على رمز opcode أحادي البايت يليه 0 أو أكثر من المعاملات. يمثل الرمز opcode العملية المراد تنفيذها ؛ يوفر المعامل جهاز Java Virtual معلومات إضافية مطلوبة لتنفيذ الرمز OPCODE. عندما يقوم جهاز افتراضي بتنفيذ تعليمات ، يمكنه استخدام العناصر الموجودة في التجمع الثابت الحالي ، أو القيم في المتغير المحلي للإطار الحالي ، أو القيم الموجودة في الجزء العلوي من المعامل في الإطار الحالي.
يقوم محرك التنفيذ التجريدي بتنفيذ تعليمات Bytecode واحدة في وقت واحد. كل مؤشر ترابط (مثيل محرك تنفيذ) لبرنامج يعمل في جهاز Java Virtual يقوم بهذه العملية. يحصل محرك التنفيذ على رمز opcode ، وإذا كان للرمز opCode معامل ، فإنه يحصل على معامله. يقوم بإجراء الإجراء المحدد بواسطة رمز opcode ومتابعة المعامل ، ثم يحصل على رمز opcode التالي. ستستمر عملية تنفيذ Bytecode هذه حتى يتم الانتهاء من مؤشر الترابط ، ويمكن تمييز إكمال الخيط من خلال العودة من طريقته الأولية أو عدم التقاط الاستثناء الذي تم إلقاؤه.
4 واجهة الطريقة المحلية
تم إعداد الواجهة المحلية Java ، والتي تسمى أيضًا JNI (JavanativeInterface) ، لقابلية النقل. تتيح واجهة الطريقة المحلية للطريقة المحلية القيام بما يلي:
تمرير أو إرجاع البيانات
متغيرات مثيل التشغيل
تشغيل متغيرات الفصل أو طرق فئة الاتصال
صفيف المعامل
قفل كائن الكومة
تحميل فئة جديدة
رمي استثناء
التقط الاستثناء الذي تم إلقاؤه بواسطة طريقة محلية تدعو طريقة Java
التقاط استثناء غير متزامن يتم إلقاؤه بواسطة الجهاز الظاهري
يشير إلى أنه لم يعد هناك حاجة إلى كائن جامع القمامة
لخص
ما سبق يدور حول هذا المقال حول فهم متعمق لهندسة الجهاز الافتراضي Java ، وآمل أن يكون مفيدًا للجميع. يمكن للأصدقاء المهتمين الاستمرار في الرجوع إلى الموضوعات الأخرى ذات الصلة على هذا الموقع. إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها. شكرا لك يا أصدقائك لدعمكم لهذا الموقع!