في وقت سابق، كتبت عدة مشاركات حول تجميع القمامة في جافا و جافا هي تمرير بالقيمة. بعد ذلك، تلقيت الكثير من الرسائل الإلكترونية لشرح مساحة الذاكرة في جافا، ذاكرة الكومة في جافا، تخصيص الذاكرة في جافا وما هي الفروق بينهم. ستجد الكثير من الإشارات إلى ذاكرة الكومة وذاكرة الكومة في كتب جافا وبرامج تعليمية ولكن نادرًا ما تجد شرحًا كاملاً حول ما هي ذاكرة الكومة والكومة من حيث البرنامج.
مساحة الذاكرة في جافا
تُستخدم مساحة الذاكرة في جافا من قبل تشغيل جافا لتخصيص ذاكرة للكائنات وفئات JRE. كلما قمنا بإنشاء كائن، يتم إنشاؤه دائمًا في مساحة الذاكرة. يعمل تجميع القمامة على ذاكرة الكومة لتحرير الذاكرة المستخدمة بواسطة الكائنات التي ليس لديها أي مرجع. يحتوي أي كائن يتم إنشاؤه في مساحة الذاكرة على وصول عالمي ويمكن الرجوع إليه من أي مكان في التطبيق.
ذاكرة الكومة في جافا
يُستخدم ذاكرة الكتلة في جافا لتنفيذ خيط. إنها تحتوي على قيم محددة للطريقة ذات الصلاحية القصيرة وإشارات إلى كائنات أخرى في الكتلة التي يتم الرجوع إليها من الطريقة. يتم الرجوع إلى ذاكرة الكتلة دائمًا بترتيب LIFO (آخر وارد أولا). عند استدعاء الطريقة، يتم إنشاء كتلة جديدة في ذاكرة الكتلة لتخزين القيم الأولية المحلية والإشارة إلى كائنات أخرى في الطريقة. بمجرد انتهاء الطريقة، تصبح الكتلة غير مستخدمة وتصبح متاحة للطريقة التالية. حجم ذاكرة الكتلة أقل بكثير مقارنة بذاكرة الكتلة.
الذاكرة الكتلية وذاكرة الكتلة في برنامج جافا
لنفهم استخدام ذاكرة الكتلة والكتلة بواسطة برنامج بسيط.
package com.journaldev.test;
public class Memory {
public static void main(String[] args) { // Line 1
int i=1; // Line 2
Object obj = new Object(); // Line 3
Memory mem = new Memory(); // Line 4
mem.foo(obj); // Line 5
} // Line 9
private void foo(Object param) { // Line 6
String str = param.toString(); //// Line 7
System.out.println(str);
} // Line 8
}
الصورة أدناه تظهر ذاكرة الكتلة والكتلة بالإشارة إلى البرنامج أعلاه وكيف يتم استخدامها لتخزين القيم الأولية والكائنات ومتغيرات الإشارة. لنتعرف على خطوات تنفيذ البرنامج.
- فور تشغيل البرنامج، يقوم بتحميل جميع فئات التشغيل في مساحة الكتلة. عند العثور على طريقة main() في السطر 1، يقوم جافا بإنشاء ذاكرة الكتلة لاستخدامها من قبل خيط الطريقة الرئيسية.
- نحن نقوم بإنشاء متغير محلي بدائي في السطر 2، لذا يتم إنشاؤه وتخزينه في ذاكرة القطعة الفرعية لطريقة main().
- نظرًا لأننا ننشئ كائنًا في السطر الثالث، يتم إنشاؤه في ذاكرة الكومة وتحتوي ذاكرة القطعة الفرعية على المرجع الخاص به. يحدث عملية مماثلة عندما ننشئ كائن Memory في السطر الرابع.
- الآن عندما نستدعي طريقة foo() في السطر الخامس، يتم إنشاء كتلة في أعلى الكومة لاستخدامها من قبل طريقة foo(). نظرًا لأن Java تنقل بالقيمة، يتم إنشاء مرجع جديد للكائن في كتلة الكومة لـ foo() في السطر السادس.
- A string is created in the 7th line, it goes in the String Pool in the heap space and a reference is created in the foo() stack space for it.
- تنتهي طريقة foo() في السطر الثامن، في هذا الوقت يصبح الكتلة الذاكرية المخصصة لـ foo() في الكومة مجانية.
- في السطر 9، تنتهي طريقة main() ويتم تدمير ذاكرة القطعة الفرعية التي تم إنشاؤها لطريقة main(). أيضًا، ينتهي البرنامج في هذا السطر، وبالتالي تقوم Java Runtime بإطلاق سراح كل الذاكرة وتنهي تنفيذ البرنامج.
الفرق بين مساحة الكومة في Java وذاكرة القطعة الفرعية
بناءً على التفسيرات أعلاه، يمكننا بسهولة الاستنتاج من التالي الفروقات بين ذاكرة الكومة وذاكرة القطعة الفرعية.
- تُستخدم ذاكرة الكومة من قبل جميع أجزاء التطبيق بينما تُستخدم ذاكرة القطعة الفرعية فقط من قبل خيط تنفيذ واحد.
- عند إنشاء كائن، يتم تخزينه دائمًا في مساحة الذاكرة الخردة (Heap) وتحتوي ذاكرة الستاك على المرجع إليه. تحتوي ذاكرة الستاك فقط على المتغيرات التمثيلية المحلية والمتغيرات المرجعية إلى الكائنات في مساحة الخردة.
- الكائنات المخزنة في الخردة يمكن الوصول إليها على مستوى عالمي في حين لا يمكن الوصول إلى ذاكرة الستاك من قبل مواضيع أخرى.
- إدارة الذاكرة في الستاك تتم بطريقة LIFO بينما تكون أكثر تعقيدًا في ذاكرة الخردة لأنها تستخدم على مستوى عالمي. يتم تقسيم ذاكرة الخردة إلى أجزاء مثل الجيل الشاب والجيل القديم وما إلى ذلك، تفاصيل إضافية على تجميع القمامة في جافا.
- ستاك ميموري ذاكرة قصيرة العمر في حين أن ذاكرة الخردة تعيش من البداية حتى نهاية تنفيذ التطبيق.
- يمكننا استخدام -Xms و -Xmx كخيارات لجهاز الإدارة الافتراضي لتحديد حجم بداية وحجم الذاكرة الخردة الأقصى. يمكننا استخدام -Xss لتحديد حجم ذاكرة الستاك.
- عندما تكون ذاكرة الستاك ممتلئة، يقوم نظام تشغيل جافا برمي
java.lang.StackOverFlowError
بينما إذا كانت ذاكرة الخردة ممتلئة، يرمي بخطأjava.lang.OutOfMemoryError: Java Heap Space
. - حجم ذاكرة الستاك صغير جدًا مقارنة بذاكرة الخردة. بسبب البساطة في تخصيص الذاكرة (LIFO)، ذاكرة الستاك سريعة جدًا مقارنة بذاكرة الخردة.
هذا كل شيء بالنسبة ل Java Heap Space vs Stack Memory فيما يتعلق بتطبيق جافا، أتمنى أن يتضح لكم كيفية تخصيص الذاكرة عند تنفيذ أي برنامج جافا.
Source:
https://www.digitalocean.com/community/tutorials/java-heap-space-vs-stack-memory