JVMMemoryModel
تقدم هذه المقالة بشكل أساسي منطقة بيانات وقت التشغيل (RunTimedataareas) الموصوفة في مواصفات JVM. تم تصميم هذه المناطق لتخزين البيانات المستخدمة من قبل JVM نفسها أو البرامج التي تعمل على JVM.
دعونا أولاً نظرة عامة على JVM ، ثم نقدم رمز Bytecode ، وأخيراً نقدم مناطق بيانات مختلفة.
ملخص
كتجريد لنظام التشغيل ، يضمن JVM أن نفس الرمز يتصرف باستمرار على أجهزة مختلفة أو أنظمة التشغيل.
على سبيل المثال:
بالنسبة للنوع الأساسي ، هو عدد صحيح موقّع 32 بت بغض النظر عن نظام التشغيل 16 بت/32 بت/64 بت. تتراوح من -2^31 إلى 2^31-1
بغض النظر عما إذا كان نظام التشغيل أو الأجهزة هو أمر كبير أو صغير بايت ، يتم التأكد من أن البيانات في الذاكرة المخزنة واستخدامها من قبل JVM هي ترتيب بايت كبير أو صغير (اقرأ البايت العالي أولاً)
قد تختلف تطبيقات JVM المختلفة إلى حد ما ، ولكنها متشابهة بشكل عام.
الصورة أعلاه هي نظرة عامة على JVM
يفسر JVM الباقين المولدين المترجم. على الرغم من أن JVM هو اختصار للأجهزة الافتراضية Java ، طالما أنها لغة يمكن تجميعها في رمز Bytecode ، يمكن تشغيلها بناءً على JVM ، مثل Scala و Groovy <� "/kf/ware/vc/" Target = "_ Blank"> VCD4NCJXWPS6QWCUX3MPIXRW3SBXETMXFZEKVT6OS19A92SLRU+GXU2NSYXNZBG9HZGVYVNPU2LKIU7Q0Q05R W91MVQ0MQXYV2+3CF41TC1XNK7UPBH+NPYO6ZWQRXAVNPU2MV8TCRJBGFZC2XVYWRLCRG7Z/Q72BVY1D9KVK3NO9A51MVQ0KGJPC 9wpg0kpha+vnpu2lxe19a92slrzai5/da00nds/cfmkgv4zwn1dglvbiblbmdpbmupvfjq0l3iys26zda00na8l3a+dqo8cd7wt NDQ0V3H5TDO0QQ05RSIS8ZQ8SNPZ8LOXKOSSCJI57PMPLWTNDQTB3EXNK70NCJRLVY1D/K/B7DVMBL47XE1TC85L3HUFS8L3A+D. QO8CD7WTNDQ0V3H5TKYULRU8LSMWO3T67XXSUOY2DF3Z7XNS7XEVBU7PTWVCD4NCJXWPIOQUTY24EPWTBA8YRXP1SHLVLTKSBHG 0UU5PSTCKEPJVD1QDXN0IGLUIHRPBWUPOANKSVS+ZCRHSNG+RBOJ1RTQ0LXETPRC6YJIYLXJTPRC6IMX4NLRS8MXVRXYTPRC6YHO yxrpdmugq29kzsmho7tmt8vksvsx4nlryfqzybt6wuuuu1xmf40/kzxs6qpc9wpg0kpha+tprc67u6tobh+chdb2rlienh y2gpoao8tmqxseds67y8yvuosklukby2tpo1xmzhun/by0pwtbxe0nte3coqpc9wpg0kpggyiglkpq == "على أساس المكدس الهندسة المعمارية "> الهندسة المعمارية القائمة على المكدس
يستخدم JVM الهندسة المعمارية القائمة على المكدس. على الرغم من أن المكدس شفاف للمطورين ، إلا أنه له دور أو تأثير مهم للغاية على رمز bytecode الذي تم إنشاؤه و JVM.
ستقوم البرامج التي طورناها بتحويل العمليات ذات المستوى المنخفض وتخزينها في Bytecode. خريطة لتعليمات التشغيل من خلال المعاملات في JVM. وفقًا لمواصفات JVM ، يتم الحصول على المعلمات المطلوبة من قبل تعليمات التشغيل من مكدس المعامل.
دعنا نعطي مثالا على إضافة رقمين. وتسمى هذه العملية IADD. فيما يلي عملية 3+4 في رمز bytecond
أول 3 و 4 في مكدس المعامل
استدعاء توجيه IADD
تعليمة IADD تنبثق رقمين من الجزء العلوي من المكدس المعامل
يتم دفع نتيجة 3+4 في مكدس المعامل للاستخدام لاحقًا
هذا النهج يسمى الهندسة المعمارية القائمة على المكدس. هناك طرق أخرى للتعامل مع العمليات ذات المستوى المنخفض ، مثل الهندسة المعمارية القائمة على السجل.
Bytecode
Java Bytecode هو نتيجة لتحويل كود مصدر Java إلى سلسلة من العمليات ذات المستوى المنخفض. تتكون كل عملية من رمز opcode أو رمز التشغيل مع معلمات طول البايت صفر أو أكثر (ولكن معظم العمليات تستخدم المعلمات التي تم الحصول عليها من خلال مكدس المعامل). يمكن أن يمثل بايت واحد 256 رقمًا ، من 0x00 إلى 0xFF ، وحاليًا إلى Java8 ، يتم استخدام ما مجموعه 204.
يسرد ما يلي أنواعًا مختلفة من الرموز الفوقية Bytecode ، بالإضافة إلى نطاقها ووصفها البسيط
الثوابت: ادفع قيمة التجمع الثابت أو قيمة معروفة في مكدس المعامل. 0x00 - 0x14
الأحمال: دفع القيم المتغيرة المحلية في مكدس المعامل. 0x15 - 0x35
المتاجر: قيمة التحميل من مكدس المعامل إلى المتغير المحلي 0x36 - 0x56
المكدس: المعالجة العملية مكدس 0x57 - 0x5F
الرياضيات: احصل على قيمة من المعامل المكدس للحساب الرياضي الأساسي 0x60 - 0x84
التحويلات: تحويل بين الأنواع 0x85 - 0x 93
comaprisons: مقارنة بين قيمتين 0x94 - 0xa6
عناصر التحكم: تنفيذ Goto ، Return ، Loop ، إلخ. عمليات التحكم 0xa7 - 0xb1
المراجع: ينفذ كائنات التخصيص أو المصفوفات ، ويحصل أو يتحقق من الإشارات إلى الكائنات والأساليب والطرق الثابتة. يمكن أيضًا استدعاء الطرق الثابتة. 0xB2 - OXC3
موسع: موسع: عمليات من فئات أخرى تمت إضافتها بعد. من القيمة 0xC4 إلى 0xC9
(ماذا تعني هذه الجملة؟ ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ماذا تعني هذه الجملة؟
محجوز: يستخدم تطبيق JVM فتحات 0xCA ، Oxfe ، Oxff
هذه العمليات البالغة 204 بسيطة للغاية ، تعطي بعض الأمثلة
تحدد IFEQ (0x99) ما إذا كانت القيمتان متساوية
يضيف IADD (0x60) رقمين
I2L (0x85) يحول فترة طويلة
ArrayLength (0xbe) يعيد طول الصفيف
POP (0x57) قم ببوب قيمة من أعلى مكدس المعامل
نحتاج إلى مترجم لإنشاء ملفات Bytecode ، ومترجم Java القياسي هو Javac في JDK.
اختبار الفئة العامة {public static void main (string [] args) {int a = 1 ؛ int b = 15 ؛ int النتيجة = إضافة (a ، b) ؛ } int static public add (int a ، int b) {int result = a + b ؛ نتيجة العودة }}يمكنك الحصول على ملف Bytecode الخاص بـ "test.class" من خلال "javac test.java". ملفات Bytecode ثنائية ، يمكننا تحويل ملفات Bytecode الثنائية إلى نموذج نص من خلال Javap
java -Verbose test.class
classfile /c:/tmp/test.class آخر تعديل 1 avr. 2015 ؛ Size 367 Bytes MD5 Checksum ADB9FF75F12FC6CE1CDDE22A9C4C7426 تم تجميعها من "Test.Java" Public Class Com.Codinggeek.jvM.Test SourceFile: "Test.Java" Minor Person. java/lang/object. LineNumberTable #9 = Utf8 Main #10 = Utf8 ([ljava/lang/string ؛) v #11 = utf8 add #12 = utf8 (ii) i #13 = utf8 sourcefile #14 = utf8 test.java #15 = nameandty #5: #6 // " #17 = UTF8 COM/CODINGGEEK/JVM/TEST #18 = UTF8 JAVA/LANG/OBJECT {public com.codinggeek.jvm.test () ؛ الأعلام: ACC_Public Code: stack = 1 ، السكان المحليون = 1 ، args_size = 1 0: aload_0 1: invokespecial #1 // method java/lang/object. الأعلام: acc_public ، acc_static رمز: stack = 2 ، السكان المحليين = 4 ، args_size = 1 0: iconst_1 1: istore_1 2: bipush 15 4: istore_2 5: iload_1 6: Iload_2 7: invokestatic #2 // method add: (ii) i 10: Istore_3 السطر 9: 11 static int add (int ، int) ؛ الأعلام: acc_public ، acc_static رمز: stack = 2 ، السكان المحليين = 3 ، args_size = 2 0: ILOAD_0 1: ILOAD_1 2: IADD 3: ISTORE_2 4: ILOAD_2 5: IRETURN LINENUMBERTABLE: السطر 12: 0 13: 4}يمكن أن نرى أن رمز bytecode ليس مجرد ترجمة بسيطة لرمز Java ، ويشمل:
وصف تجمع ثابت للفصل. التجمعات الثابتة هي مناطق بيانات JVM المستخدمة لتخزين بيانات التعريف ، مثل أسماء الأسلوب ، وقوائم المعلمات ، وما إلى ذلك داخل الفصل. عندما تقوم JVM بتحميل فئة ، سيتم تحميل البيانات الوصفية في التجمع الثابت
توفير معلومات الموضع المحددة للوظائف ومتغيرات TMALL في رمز BYTECODE من خلال جدول رقم الصف والجدول المتغير المحلي.
ترجمة رمز Java (بما في ذلك بنيات فئة الوالدين المخفية)
يوفر عمليات أكثر تحديدًا على مداخن المعامل وطرق أكثر اكتمالا لتمرير والحصول على المعلمات
فيما يلي وصف بسيط لمعلومات تخزين ملفات Bytecode
classfile {u4 magic ؛ u2 minor_version ؛ u2 major_version ؛ u2 statter_pool_count ؛ cp_info statter_pool [constant_pool_count-1] ؛ u2 Access_Flags ؛ u2 this_class ؛ u2 super_class ؛ u2 interfaces_count ؛ u2 واجهات [interfaces_count] ؛ u2 fields_count ؛ field_info fields [fields_count] ؛ u2 attributes_count ؛ سمات attribute_info [attributes_count] ؛}منطقة بيانات وقت التشغيل
منطقة بيانات وقت التشغيل هي منطقة الذاكرة المصممة لتخزين البيانات. هذه البيانات مخصصة للاستخدام من قبل المطورين أو JVM داخليًا.
كومة
يتم إنشاء الكومة عند بدء تشغيل JVM ويتم مشاركتها بواسطة جميع مؤشرات الترابط JVM. يتم تخصيص جميع مثيلات الفصل والصفوف للكومة (التي تم إنشاؤها بواسطة New).
يجب إدارة الكومة من قبل جامع القمامة ، المسؤول عن إطلاق الأشياء التي أنشأها المطور ولن يتم استخدامها مرة أخرى.
بالنسبة لاستراتيجية جمع القمامة ، يتم تحديدها من خلال تطبيق JVM (على سبيل المثال ، توفر Hotspot خوارزميات متعددة).
هناك حد أقصى لذاكرة الكومة. إذا تم تجاوز هذه القيمة ، فسوف يلقي JVM استثناء OutofMemroy.
منطقة الطريقة
تتم مشاركة منطقة الطريقة أيضًا من قبل جميع مؤشرات الترابط من JVM. يتم إنشاء الشيء نفسه مع بدء التشغيل JVM. يتم تحميل البيانات المخزنة في منطقة الأسلوب من رمز Bytecode بواسطة charloader ، والذي سيكون موجودًا باستمرار أثناء تشغيل التطبيق ، ما لم يتم تدمير جهاز تحميل الفصل أو إيقاف JVM.
تقوم منطقة الطريقة بتخزين البيانات التالية:
معلومات الفئة (اسم السمة ، اسم الطريقة ، اسم الفئة الوالدية ، اسم العذر ، الإصدار ، إلخ)
الأساليب و bytecodes
تم إنشاء تجمع ثابت وقت التشغيل عند تحميل كل فئة
مواصفات JVM لا تجبر المناطق على تنفيذها في الكومة. قبل JAVA7 ، نفذت نقطة الساخنة مناطق الطريقة باستخدام منطقة تسمى بيرجن. الفرقة الدائمة متاخمة للكومة (إدارة الذاكرة هي نفس الكومة) ، فإن البت الافتراضي هو 64 ميجابايت
بدءًا من Java8 ، يستخدم HptSpot ذاكرة محلية منفصلة لتنفيذ منطقة الطريقة وتسمية منطقة البيانات الوصفية (MetAspace). الحد الأقصى للمساحة المتاحة في منطقة البيانات الوصفية هو الذاكرة المتاحة للنظام بأكمله.
إذا لم تتمكن الأسلوب من التقدم بطلب للحصول على الذاكرة المتاحة ، فسيقوم JVM أيضًا بإلقاء OutofMemoryError.
حمام سباحة ثابت وقت التشغيل
تجمع وقت التشغيل الثابت هو جزء من منطقة الطريقة. نظرًا لأهمية تشغيل تجمع ثابت إلى البيانات الوصفية ، يتم وصفه بشكل منفصل في مواصفات Java خارج منطقة الطريقة. ينمو حمام السباحة الثابت في وقت التشغيل مع الفئات والواجهات المحملة.
التجمعات الثابتة هي قليلا من طاولة بناء الجملة باللغات التقليدية. بمعنى آخر ، عند استدعاء فئة أو طريقة أو خاصية ، يبحث JVM عن العنوان الحقيقي لهذه البيانات في الذاكرة من خلال تجمع وقت التشغيل. يحتوي تجمع وقت التشغيل الثابت أيضًا على ثوابت حرفية أو أنواع بدائية
aristng myString = "هذا هو سلسلة litteral" ثابت int my_constant = 2 ؛
PC (عداد البرنامج) سجل (لكل موضوع) سجل الكمبيوتر (لكل موضوع)
كل مؤشر ترابط له سجل الكمبيوتر الخاص به (عداد البرنامج) ، والذي يتم إنشاؤه مع إنشاء مؤشرات الترابط. يمكن لكل مؤشر ترابط تنفيذ طريقة واحدة فقط في وقت ما ، تسمى الطريقة الحالية للمعلومات. يحتوي سجل الكمبيوتر على عنوان JVM الذي يقوم حاليًا بتنفيذ التعليمات (في منطقة الطريقة).
إذا كانت الطريقة التي تم تنفيذها حاليًا طريقة محلية ، فإن قيمة سجل الكمبيوتر غير محددة
مكدس الجهاز الظاهري لكل مؤشر ترابط-java-virtual-machine-stacks-per-trhread "> مكدس الجهاز الظاهري (لكل مؤشر ترابط) مكدسات الجهاز الظاهري Java (لكل مؤشر ترابط)
تقوم مكدس الجهاز الظاهري بتخزين إطارات متعددة ، لذلك قبل وصف المكدس ، دعنا نلقي نظرة على الإطارات أولاً.
إطارات
الإطار عبارة عن بنية بيانات تحتوي على بيانات متعددة تمثل الطريقة الحالية التي تنفذها مؤشر الترابط:
مكدس المعامل: كما ذكرنا من قبل ، تعليمات Bytecode تستخدم مكدس المعامل لتمرير المعلمات
صفيف متغير محلي: تحتوي هذه الصفيف على جميع المتغيرات المحلية ضمن نطاق الطريقة التي تم تنفيذها حاليًا. يمكن أن تحتوي هذه المجموعة على نوع بدائي أو مرجع أو عنوان إرجاع. يتم تحديد حجم الصفيف المتغير المحلي في وقت الترجمة. يستخدم JVM المتغيرات المحلية لتمرير المعلمات عند استدعاء الطريقة ، ويتم إنشاء صفيف المتغير المحلي للطريقة المكالمة من خلال كومة المعامل لطريقة الاتصال.
مرجع تجمع وقت التشغيل: الإشارات إلى المجموعة الثابتة للطريقة الحالية للفئة الحالية. يستخدم JVM مراجع تجمع ثابتة لإشارات المرور إلى مراجع الذاكرة الحقيقية.
كومة (كومة)
يحتوي كل مؤشر ترابط JVM على مكدس JVM خاص ، والذي يتم إنشاؤه في نفس الوقت مثل الخيط. Java Virtual Machine Stack Stack Stands. في كل مرة يتم استدعاء طريقة ، يتم إنشاء إطار ودفعه إلى مكدس الجهاز الظاهري. عند تنفيذ هذه الطريقة ، سيتم تدمير الإطار أيضًا (بغض النظر عما إذا كان يتم تنفيذ الطريقة بشكل طبيعي أو يتم إلقاء استثناء)
يتوفر إطار واحد فقط أثناء تنفيذ موضوع. يسمى هذا الإطار الإطار الحالي.
عادة ما تكون العمليات على المتغيرات المحلية ومداخن المعامل مصحوبة بالإشارات إلى الإطار الحالي.
دعونا نلقي نظرة على مثال آخر على الإضافة
int public add (int a ، int b) {return a + b ؛} public void functiona () {// بعض التعليمات البرمجية بدون استدعاء وظيفة int result = add (2،3) ؛ // اتصل على الوظيفة ب // بعض التعليمات البرمجية بدون استدعاء وظيفة}داخل الطريقة A ، الإطار A هو الإطار الحالي ، الموجود في الجزء العلوي من مكدس الجهاز الظاهري. في بداية استدعاء طريقة إضافة ، يتم إنشاء إطار جديد B ودفعه إلى مكدس الجهاز الظاهري. يصبح الإطار B الإطار الحالي الجديد.
تمتلئ مجموعة المتغير المحلي من الإطار B بالبيانات في مكدس المعامل من الإطار A. عند انتهاء طريقة إضافة ، يتم تدمير الإطار B وإعادة تأسيس الإطار A كإطار الحالي. يتم دفع نتيجة طريقة الإضافة إلى كومة المعامل من الإطار A ، بحيث يمكن أن تحصل الطريقة A على نتيجة إضافة من خلال مكدس المعامل من الإطار A.
لخص
ما سبق هو كل شيء عن تحليل منطقة البيانات لوقت تشغيل الجهاز الافتراضي Java. آمل أن يكون ذلك مفيدًا للجميع.
إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها.