تشرح هذه المقالة بشكل أساسي مبدأ عملها بالتفصيل من خلال تحليل المكدس والكومة والتجمع الثابت لتخصيص ذاكرة Java.
1. نموذج ذاكرة الجهاز الظاهري جافا
التسجيل: ليس لدينا أي سيطرة على البرنامج. Stack: يخزن الأنواع الأساسية من البيانات ومراجع الكائنات، لكن الكائن نفسه لا يتم تخزينه في المكدس، بل يتم تخزينه في الكومة: يخزن البيانات التي تم إنشاؤها باستخدام المجال الثابت : يتم تخزينه في تجمع ثابت للعضو الثابت محددًا بثابت: تخزين الثوابت بخلاف ذاكرة الوصول العشوائي: مساحة تخزين دائمة مثل القرص الصلب.
2. تجمع مستمر
يشير التجمع الثابت إلى التجمع الثابت الذي يتم تحديده في وقت الترجمة وحفظه في الذاكرة المترجمة. بعض البيانات في ملف الفصل. بالإضافة إلى القيم الثابتة (النهائية) التي تحتوي على أنواع أساسية متنوعة (مثل int وlong وغيرها) وأنواع الكائنات (مثل String وrays) المحددة في الكود، فإنها تحتوي أيضًا على بعض المراجع الرمزية في شكل نص ، مثل:
1. أسماء الفئات والواجهات المؤهلة بالكامل؛
2. اسم الحقل والواصف؛
3. الأساليب والأسماء والواصفات.
يجب أن يحتفظ الجهاز الظاهري بتجميع ثابت لكل نوع تم تحميله. التجمع الثابت عبارة عن مجموعة مرتبة من الثوابت التي يستخدمها هذا النوع، بما في ذلك الثوابت المباشرة (ثوابت السلسلة والأعداد الصحيحة والفاصلة العائمة) والمراجع الرمزية للأنواع والحقول والأساليب الأخرى. بالنسبة لثوابت السلسلة، تكون قيمها موجودة في التجمع الثابت. يوجد التجمع الثابت في JVM على شكل جدول في الذاكرة بالنسبة لنوع السلسلة، يوجد جدول CONSTANT_String_info ذو طول ثابت يستخدم لتخزين قيم السلسلة الحرفية فقط . بعد قولي هذا، يجب أن يكون لديك فهم واضح لموقع تخزين قيم السلسلة في التجمع الثابت. عند تنفيذ البرنامج، سيتم تخزين التجمع الثابت في منطقة الطريقة بدلاً من الكومة.
3. كومة في تخصيص ذاكرة جافا
الوحدة الأساسية للمكدس هي الإطار (أو إطار المكدس): عند تشغيل مؤشر ترابط Java، يقوم جهاز Java الظاهري بتخصيص مكدس Java للخيط. عندما ينفذ الخيط طريقة Java معينة، فإنه يدفع الإطار إلى مكدس Java. يُستخدم هذا الإطار لتخزين المعلمات والمتغيرات المحلية والمعاملات ونتائج العمليات الوسيطة وما إلى ذلك. عندما يكتمل تنفيذ هذه الطريقة، سيتم إخراج الإطار من المكدس. جميع البيانات الموجودة في مكدس Java خاصة، ولا يمكن لأي مؤشر ترابط آخر الوصول إلى بيانات مكدس الخيط. يتم تخصيص بعض الأنواع الأساسية من البيانات المتغيرة والمتغيرات المرجعية للكائنات المحددة في الوظيفة في ذاكرة المكدس الخاصة بالوظيفة. عندما يتم تعريف متغير في كتلة من التعليمات البرمجية، تقوم Java بتخصيص مساحة الذاكرة للمتغير على المكدس. عندما يخرج المتغير من النطاق، ستقوم Java تلقائيًا بتحرير مساحة الذاكرة المخصصة للمتغير، ويمكن استخدام مساحة الذاكرة على الفور. استخدامها لأغراض أخرى.
4. كومة في تخصيص ذاكرة جافا
يتم استخدام الكومة الموجودة في جهاز Java الظاهري لتخزين الكائنات والمصفوفات التي تم إنشاؤها بواسطة new. تتم إدارة الذاكرة المخصصة في الكومة من خلال آلية تجميع البيانات المهملة التلقائية لجهاز Java الظاهري. ببساطة، بالمقارنة مع المكدس، يتم استخدام الكومة بشكل أساسي لتخزين كائنات Java، ويتم استخدام المكدس بشكل أساسي لتخزين مراجع الكائنات... بعد إنشاء مصفوفة أو كائن في الكومة، يمكن أيضًا إنشاء متغير خاص تم تعريفه في المكدس، بحيث تكون قيمة هذا المتغير في المكدس مساوية للعنوان الأول للمصفوفة أو الكائن في ذاكرة الكومة. يصبح هذا المتغير في المكدس هو المتغير المرجعي للمصفوفة أو الكائن. المتغير المرجعي يعادل إعطاء اسم لمصفوفة أو كائن. يمكنك بعد ذلك استخدام المتغير المرجعي في المكدس للوصول إلى المصفوفة أو الكائن الموجود في الكومة في البرنامج. المتغير المرجعي يعادل إعطاء اسم لمصفوفة أو كائن.
المتغيرات المرجعية هي متغيرات عادية يتم تخصيصها على المكدس عند تعريفها، ويتم تحرير المتغيرات المرجعية بعد تشغيل البرنامج خارج نطاقه. يتم تخصيص المصفوفات والكائنات نفسها في الكومة. حتى إذا تم تشغيل البرنامج خارج كتلة التعليمات البرمجية حيث يوجد البيان الذي يستخدم جديد لإنشاء المصفوفة أو الكائن، فلن يتم تحرير الذاكرة التي يشغلها المصفوفة والكائن نفسه لا تحتوي الكائنات على متغيرات مرجعية تشير إليها، وتصبح قمامة ولا يمكن استخدامها بعد الآن، لكنها لا تزال تشغل مساحة الذاكرة وسيتم جمعها (إصدارها) بواسطة جامع البيانات المهملة في وقت غير محدد لاحقًا. وهذا أيضًا هو السبب وراء استهلاك Java لمساحة أكبر من الذاكرة. في الواقع، تشير المتغيرات الموجودة في المكدس إلى المتغيرات الموجودة في ذاكرة الكومة. وهذا مؤشر في Java!
كومة Java هي منطقة بيانات في وقت التشغيل يتم من خلالها تخصيص مساحة لكائنات الفئة من خلال تعليمات مثل new وnewaray وanewarray وmultianewarray، ولا تتطلب إصدار كود البرنامج بشكل صريح المسؤول، تتمثل ميزة الكومة في أنها يمكنها تخصيص حجم الذاكرة ديناميكيًا، ولا يحتاج المترجم إلى إخبار العمر مسبقًا، لأنه يخصص الذاكرة ديناميكيًا في وقت التشغيل، وسيقوم جامع البيانات المهملة في Java تلقائيًا بجمع تلك التي لم تعد مستخدمة ولكن العيب هو أنه نظرًا للحاجة إلى تخصيص الذاكرة ديناميكيًا في وقت التشغيل، فإن سرعة الوصول تكون بطيئة.
تتمثل ميزة المكدس في أن سرعة الوصول أسرع من الكومة، وتأتي في المرتبة الثانية بعد السجل، ويمكن مشاركة بيانات المكدس. لكن العيب هو أنه يجب تحديد حجم وعمر البيانات المخزنة في المكدس، كما أن هناك نقصًا في المرونة. يقوم المكدس بشكل أساسي بتخزين بعض الأنواع الأساسية من البيانات المتغيرة (int، short، long، byte، float، double، boolean، char) ومقابض الكائنات (المراجع).
الميزة الخاصة المهمة جدًا للمكدس هي أنه يمكن مشاركة البيانات المخزنة في المكدس. لنفترض أننا نحدد أيضًا:
int a=3; int b=3; يقوم المترجم أولاً بمعالجة int a = 3; أولاً يقوم بإنشاء مرجع للمتغير a على المكدس، ثم يتحقق مما إذا كانت هناك قيمة 3 في المكدس. سيتم تعيينه على 3، ثم قم بالإشارة إلى 3. ثم قم بمعالجة int b = 3؛ بعد إنشاء المتغير المرجعي لـ b، نظرًا لوجود قيمة 3 بالفعل في المكدس، سيتم توجيه b مباشرة إلى 3. بهذه الطريقة، يظهر a وb في نفس الوقت، وكلاهما يشير إلى الحالة 3.
في هذا الوقت، إذا تم تعيين a=4 مرة أخرى، فسيقوم المترجم بإعادة البحث عما إذا كانت هناك قيمة 4 في المكدس سوف يشير مباشرة إلى هذا العنوان. ولذلك، فإن التغييرات في قيمة أ لن تؤثر على قيمة ب.
تجدر الإشارة إلى أن هذا النوع من مشاركة البيانات يختلف عن مشاركة مرجعي كائنين يشيران إلى كائن واحد في نفس الوقت، لأنه في هذه الحالة لن يؤثر تعديل a على b، بل يتم إكماله بواسطة المترجم، والذي مفيد لتوفير المساحة. إذا قام متغير مرجع كائن بتعديل الحالة الداخلية للكائن، فسوف يؤثر ذلك على متغير مرجع كائن آخر.