مرحبا بالجميع! نريد أن نتزامن مع ترجمة مواد اليوم مع إطلاق سلسلة رسائل جديدة في دورة
Java Developer ، والتي تبدأ غدًا. حسنًا ، لنبدأ.
JVM يمكن أن يكون وحشا معقدة. لحسن الحظ ، يتم إخفاء معظم هذا التعقيد أسفل الغطاء ، وكثيراً ما لا داعي للقلق ، بصفتنا مطوري التطبيقات والمسؤولين عن النشر. على الرغم من تزايد شعبية التكنولوجيا في نشر التطبيقات في الحاويات ، إلا أنها تستحق الاهتمام بتخصيص الذاكرة في JVM.
نوعان من الذاكرةيقسم JVM الذاكرة إلى فئتين رئيسيتين: الكومة وغير الكومة. الكومة هي جزء من ذاكرة JVM التي يعرفها المطورون. يتم تخزين الكائنات التي تم إنشاؤها بواسطة التطبيق هنا. تبقى هناك حتى يتم إزالتها من قبل جامع القمامة. عادةً ما يختلف حجم الكومة الذي يستخدمه التطبيق وفقًا للتحميل الحالي.
تنقسم الذاكرة خارج الكومة إلى عدة مناطق. في HotSpot ، يمكنك استخدام آلية
تتبع الذاكرة الأصلية (NMT) لاستكشاف مناطق هذه الذاكرة. يرجى ملاحظة أنه على الرغم من أن NMT لا يتتبع استخدام جميع الذاكرة الأصلية (
على سبيل المثال ، لا يتتبع تخصيص الذاكرة الأصلية بواسطة رمز الجهة الخارجية ) ، إلا أن إمكاناتها كافية لمعظم تطبيقات Spring النموذجية. لاستخدام NMT ، قم بتشغيل التطبيق باستخدام
-XX:NativeMemoryTracking=summary
واستخدام
ملخص jcmd VM.native_memory راجع المعلومات حول الذاكرة المستخدمة.
دعونا ننظر في استخدام NMT كمثال من صديقنا القديم Petclinic . يوضح الرسم البياني أدناه استخدام ذاكرة JVM وفقًا لبيانات NMT (مطروحًا منها الحمل NMT الخاص به) عند بدء تشغيل Petclinic بأقصى حجم كومة الذاكرة المؤقتة 48 ميجابايت (
-Xmx48M
):

كما ترون ، تمثل الذاكرة الموجودة خارج الكومة معظم حسابات JVM المستخدمة ، ولا تعد ذاكرة الكومة سوى سدس المجموع. في هذه الحالة ، تبلغ مساحتها حوالي 44 ميغابايت (تم استخدام 33 ميغابايت منها مباشرةً بعد تجميع البيانات المهملة). بلغ إجمالي استخدام ذاكرة الكومة 223 ميغابايت.
مجالات الذاكرة الأصليةمساحة الفصل المضغوطة : تُستخدم لتخزين معلومات حول الفئات المحملة. تقتصر على المعلمة
MaxMetaspaceSize
. دالة لعدد الفئات التي تم تحميلها.
ملاحظة المترجملسبب ما ، يكتب المؤلف عن مساحة الفصل المضغوط ، وليس عن مساحة الفصل بأكملها. تعد مساحة مساحة الفئة المضغوطة جزءًا من مساحة الفصل ، MaxMetaspaceSize
المعلمة MaxMetaspaceSize
من حجم مساحة الفصل بأكملها ، وليس فقط مساحة الفصل المضغوطة. للحد من "مساحة الفئة المضغوطة" ، يتم استخدام المعلمة CompressedClassSpaceSize
.
من هنا :
إذا كان UseCompressedOops
قيد التشغيل UseCompressedClassesPointers
، UseCompressedClassesPointers
استخدام منطقتين مختلفتين منطقياً من الذاكرة الأصلية لبيانات تعريف الفئة ...
يتم تخصيص منطقة لهذه المؤشرات فئة المضغوطة (إزاحة 32 بت). يمكن تعيين حجم المنطقة باستخدام CompressedClassSpaceSize
وهو 1 غيغابايت (GB) افتراضيًا ...
ينطبق MaxMetaspaceSize
على مجموع مساحة الفئة المضغوطة الملتزم بها ومساحة بيانات تعريف الفئة الأخرى
إذا تم UseCompressedOops
المعلمة UseCompressedOops
استخدام UseCompressedOops
، UseCompressedOops
استخدام منطقتين مختلفتين منطقياً من الذاكرة الأصلية لبيانات تعريف الفئة ...
بالنسبة للمؤشرات المضغوطة ، يتم تخصيص منطقة ذاكرة (إزاحة 32 بت). يمكن تعيين حجم هذه المنطقة عن طريق CompressedClassSpaceSize
وبشكل افتراضي هو 1 غيغابايت ...
تشير المعلمة MaxMetaspaceSize
إلى مجموع مساحة المؤشر المضغوط ومساحة بيانات تعريف الفئة الأخرى.
- خيط: الذاكرة المستخدمة من قبل المواضيع في JVM. وظيفة عدد من المواضيع قيد التشغيل.
- ذاكرة التخزين المؤقت للتعليمات البرمجية: الذاكرة المستخدمة بواسطة JIT لتشغيله. دالة لعدد الفئات التي تم تحميلها. يقتصر على
ReservedCodeCacheSize
. يمكنك تقليل إعداد JIT ، على سبيل المثال ، عن طريق تعطيل الترجمة المتدرجة. - GC (أداة تجميع مجمعي البيانات المهملة): تخزن البيانات المستخدمة من قبل أداة تجميع البيانات المهملة. يعتمد على جامع القمامة المستخدم.
- الرمز: يخزن أحرفًا مثل أسماء الحقول وتواقيع الطريقة والسلاسل الداخلية. الاستخدام المفرط لذاكرة الشخصية قد يشير إلى أن الأسطر متداخلة للغاية.
- داخلي: يخزن البيانات الداخلية الأخرى التي لم يتم تضمينها في أي من المناطق الأخرى.
الخلافاتبالمقارنة مع كومة الذاكرة المؤقتة ، يتغير ذاكرة إيقاف التشغيل أقل تحت الحمل. بمجرد أن يقوم التطبيق بتحميل جميع الفئات التي سيتم استخدامها وتحسّن JIT بالكامل ، فسيذهب كل شيء إلى حالة مستقرة. لرؤية انخفاض في استخدام
مساحة الفصل المضغوط ، يجب إزالة أداة تحميل الفئة التي تم تحميلها بواسطة أداة تجميع مجمعي البيانات المهملة. كان هذا شائعًا في الماضي عندما تم نشر التطبيقات في حاويات servlet أو خوادم التطبيقات (تمت إزالة أداة تحميل فئة التطبيق من قبل جامع البيانات المهملة عند إزالة التطبيق من خادم التطبيق) ، ولكن هذا نادرًا ما يحدث مع الأساليب الحديثة لنشر التطبيق.
تكوين JVMتكوين JVM لاستخدام ذاكرة الوصول العشوائي المتاحة بكفاءة ليس بالأمر السهل. إذا قمت بتشغيل JVM مع المعلمة
-Xmx16M
ولا تتوقع استخدام أكثر من 16 ميجابايت من الذاكرة ، فستحصل على مفاجأة غير سارة.
مجال مثير للاهتمام من ذاكرة JVM هو ذاكرة التخزين المؤقت رمز JIT. بشكل افتراضي ، سوف يستخدم HotSpot JVM ما يصل إلى 240 ميجابايت. إذا كانت ذاكرة التخزين المؤقت للرمز صغيرة جدًا ، فقد لا يكون لدى JIT مساحة كافية لتخزين بياناتها ، ونتيجة لذلك ، سيتم تقليل الأداء. إذا كانت ذاكرة التخزين المؤقت كبيرة جدًا ، فقد تضيع الذاكرة. عند تحديد حجم ذاكرة التخزين المؤقت ، من المهم مراعاة تأثيرها على كل من استخدام الذاكرة والأداء.
عند التشغيل في حاوية Docker ، فإن أحدث إصدارات Java
تدرك الآن قيود ذاكرة الحاوية وتحاول تغيير حجم ذاكرة JVM وفقًا لذلك. لسوء الحظ ، غالبًا ما يتم تخصيص الكثير من الذاكرة خارج كومة الذاكرة المؤقتة وغير كافية في كومة الذاكرة المؤقتة. افترض أن لديك تطبيقًا قيد التشغيل في حاوية بها معالجان و 512 ميجابايت من الذاكرة المتوفرة. تريد معالجة المزيد من عبء العمل وزيادة عدد المعالجات إلى 4 والذاكرة إلى 1 جيجابايت. كما ناقشنا أعلاه ، يتغير حجم الكومة عادةً مع الحمل ، وتتغير الذاكرة خارج الكومة بشكل ملحوظ. لذلك ، نتوقع أن يتم تخصيص معظم 512 ميغا بايت إضافية إلى الكومة لمعالجة الحمل الزائد. لسوء الحظ ، لن تقوم JVM بذلك افتراضيًا ، وستوزع ذاكرة إضافية بشكل أو بآخر بالتساوي بين الذاكرة الموجودة على الكومة وإيقاف الكومة.
لحسن الحظ ، لدى فريق CloudFoundry معرفة واسعة بتخصيص الذاكرة في JVM. إذا قمت بتنزيل التطبيقات على CloudFoundry ، فستقوم حزمة الإنشاء تلقائيًا بتطبيق هذه المعرفة عليك. إذا كنت لا تستخدم CloudFoudry أو ترغب في فهم المزيد حول كيفية تكوين JVM ، فمن المستحسن قراءة
وصف الإصدار الثالث من
حاسبة ذاكرة Java buildpack .
ماذا يعني هذا لفصل الربيعيقضي فريق Spring الكثير من الوقت في التفكير في الأداء واستخدام الذاكرة ، مع الأخذ في الاعتبار إمكانية استخدام الذاكرة في كومة الذاكرة المؤقتة وإيقاف الكومة. تتمثل إحدى الطرق للحد من استخدام الذاكرة خارج الكومة في جعل أجزاء الإطار متعددة الاستخدامات قدر الإمكان. مثال على ذلك هو استخدام Reflection لإنشاء وحقن التبعيات في حبوب التطبيق. من خلال استخدام Reflection ، يظل مقدار رمز الإطار الذي تستخدمه ثابتًا ، بغض النظر عن عدد حبوب التطبيق. لتحسين وقت بدء التشغيل ، نستخدم ذاكرة التخزين المؤقت على الكومة ، ونقوم بمسح ذاكرة التخزين المؤقت هذه بعد اكتمال بدء التشغيل. يمكن بسهولة تنظيف ذاكرة كومة الذاكرة المؤقتة بواسطة أداة تجميع مجمعي البيانات المهملة لتوفير المزيد من الذاكرة المتاحة للتطبيق الخاص بك.
تقليديا ، نحن في انتظار تعليقاتكم على المواد.