يجب أن يعلم جميع الأصدقاء الذين يدرسون Java أن Java كانت تستخدم شعار استقلال النظام الأساسي منذ البداية، قائلة "اكتب مرة واحدة، وقم بالتشغيل في أي مكان". ، لتحقيق استقلال اللغة، ثم بنية الملف للفئة في نظام جافا أو من المهم جدًا أن نقول إنه كود ثانوي. في الواقع، كان لدى Java مجموعتان من المواصفات منذ البداية، إحداهما هي مواصفات لغة Java، والأخرى هي مواصفات آلة Java الافتراضية، وتنص مواصفات لغة Java على القيود فقط المتعلقة بلغة Java وقواعدها، وقد تم تصميم مواصفات الجهاز الظاهري حقًا من منظور متعدد الأنظمة الأساسية. سنأخذ اليوم مثالاً عمليًا لمعرفة الشكل الذي يجب أن يبدو عليه الرمز الثانوي المطابق لملف Class في Java. ستشرح هذه المقالة أولاً بشكل عام محتوى الفئة، ثم ستستخدم فئة Java الفعلية لتحليل بنية ملف الفئة.
وقبل المتابعة علينا أولا توضيح النقاط التالية:
1) تتكون ملفات الفئة من تدفقات بايت مبنية على 8 بايت، ويتم ترتيبها بدقة بالترتيب المحدد، ولا توجد فجوات بين البايتات، بالنسبة للملفات التي تتجاوز 8 بايت، سيتم تخزين البيانات بترتيب Big-Endian. وهذا يعني أنه يتم تخزين البايت عالي الترتيب في العنوان المنخفض، ويتم تخزين البايت ذو الترتيب المنخفض في العنوان العالي. يعد هذا أيضًا مفتاح ملفات الفئات عبر الأنظمة الأساسية، نظرًا لأن بنية PowerPC تستخدم ترتيب تخزين Big-Endian، بينما تستخدم معالجات سلسلة x86 ترتيب تخزين Little-Endian، لذلك يتم الاحتفاظ بملفات الفئة تحت كل بنية معالج تخزين موحد من أجل ذلك، يجب توحيد مواصفات الجهاز الظاهري.
2) تستخدم بنية ملف الفئة بنية تشبه لغة C لتخزين البيانات. هناك نوعان رئيسيان من عناصر البيانات، يتم استخدام الأرقام غير الموقعة والجداول غير الموقعة للتعبير عن الأرقام ومراجع الفهرس والسلاسل، مثل u1 وu2 يمثل u4 وu8 بايت واحد و2 بايت و4 بايت و8 بايت من الأرقام غير الموقعة على التوالي، والجدول عبارة عن بنية مركبة تتكون من أرقام متعددة غير موقعة وجداول أخرى. ربما ليس لدى الجميع هنا فكرة واضحة عن ماهية الأرقام والجداول غير الموقعة، لكن لا يهم، سأشرح ذلك بالأمثلة عندما أقدم الأمثلة أدناه.
بعد توضيح النقطتين أعلاه، دعونا نلقي نظرة على البيانات المحددة الموجودة في تدفق البايتات مرتبة بترتيب صارم في ملف الفئة:
عند النظر إلى الصورة أعلاه، هناك شيء واحد نحتاج إلى الانتباه إليه، مثل cp_info، يمثل cp_info التجمع الثابت. في الصورة أعلاه، يتم استخدام Constant_pool[constant_pool_count-1] لتمثيل التجمع الثابت مع Constant_pool_co. ثابت unt-1، يتم التعبير عنه في شكل مصفوفة هنا، لكن لا تعتقد خطأً أن الأطوال الثابتة لجميع التجمعات الثابتة هي نفسها. في الواقع، يستخدم هذا المكان طريقة المصفوفة فقط لتسهيل الوصف، ولكن ليس الأمر كذلك في لغات البرمجة، مصفوفة من النوع int لها نفس طول كل int. بعد توضيح هذه النقطة، دعونا ننظر إلى الوراء ونرى ما يمثله كل عنصر في الصورة أعلاه على وجه التحديد.
1) يمثل u4 السحري الرقم السحري، ويشغل الرقم السحري 4 بايت. ماذا يفعل الرقم السحري؟ وهذا يعني في الواقع أن نوع الملف هو ملف فئة، وليس صورة JPG أو فيلم AVI. الرقم السحري المطابق لملف الفئة هو 0xCAFEBABE.
2) يمثل u2 minor_version رقم الإصدار الثانوي لملف الفئة، ورقم الإصدار هذا هو تمثيل رقم غير موقع من النوع u2.
3) يمثل u2 Major_version رقم الإصدار الرئيسي لملف Class، ورقم الإصدار الرئيسي هو تمثيل رقم غير موقع لنوع u2. يتم استخدام main_version وminor_version بشكل أساسي للإشارة إلى ما إذا كان الجهاز الظاهري الحالي يقبل الإصدار الحالي من ملف Class. تختلف إصدارات ملفات الفئة التي تم تجميعها بواسطة إصدارات مختلفة من برامج التحويل البرمجي Java. يدعم الإصدار الأعلى من الجهاز الظاهري بنية ملف الفئة التي تم تجميعها بواسطة إصدار أقل من المترجم. على سبيل المثال، يدعم الجهاز الظاهري المطابق لـ Java SE 6.0 بنية ملفات الفئة التي تم تجميعها بواسطة مترجم Java SE 5.0، ولكن ليس العكس.
4) يمثل u2 Constant_pool_count عدد التجمعات الثابتة. نحن هنا بحاجة إلى التركيز على ما هو التجمع الثابت، يرجى عدم الخلط بينه وبين التجمع الثابت لوقت التشغيل في نموذج ذاكرة Jvm قيمة الثابت النهائي أو أو القيمة الأولية لسمة معينة، وما إلى ذلك، بينما تقوم مراجع الرموز بشكل أساسي بتخزين الأسماء المؤهلة بالكامل للفئات والواجهات، وأسماء الحقول والواصفات، وأسماء الطرق والواصفات، وقد تكون الأسماء هنا سهلة الفهم للجميع، كما هو الحال بالنسبة لـ مفهوم الواصفات سنتحدث عنه لاحقا عندما نناقش جدول الحقل وجدول الطريقة. بالإضافة إلى ذلك، يعلم الجميع أن نموذج ذاكرة Jvm يتكون من الكومة والمكدس ومنطقة الطريقة وعداد البرنامج، وهناك منطقة في منطقة الطريقة تسمى التجمع الثابت لوقت التشغيل. الأشياء المخزنة في التجمع الثابت لوقت التشغيل هي في الواقع خلود المترجم.مراجع حرفية ورمزية مختلفة، لكن تجمع ثابت وقت التشغيل ديناميكي ويمكنه إضافة ثوابت أخرى إليه في وقت التشغيل.
5) يمثل cp_info التجمع الثابت الذي يحتوي على مختلف المراجع الحرفية والرموز المذكورة أعلاه. يوجد إجمالي 14 عنصرًا من عناصر البيانات الموضوعة في التجمع الثابت في Java Virtual Machine Specification Java SE 7 Edition. كل ثابت عبارة عن جدول، ويستخدم كل ثابت علامة جزئية مشتركة للإشارة إلى نوع ثابته.
التفاصيل المحددة موضحة بإيجاز أدناه وسنعمل على تحسينها في الأمثلة اللاحقة.
علامة علامة CONSTANT_Utf8_info هي 1، وعلامة علامة CONSTANT_Integer_info للسلسلة المشفرة UTF-8 هي 3، وعلامة علامة CONSTANT_Float_info ذات العدد الصحيح هي 4، وعلامة علامة CONSTANT_Long_info الحرفية ذات النقطة العائمة هي 5، وعلامة علامة CONSTANT_Double_info ذات العدد الصحيح الطويل هي 6، علامة العلامة CONSTANT_Class_info الحرفية ذات الدقة المزدوجة هي 7، المرجع الرمزي لعلامة CONSTANT_String_info للفئة أو الواجهة هو 8، والعلامة CONSTANT_Fieldref_info الحرفية لنوع السلسلة هي 9، والمرجع الرمزي لحقل علامة CONSTANT_Methodref_info هو 10، والمرجع الرمزي للطريقة في علامة الفئة CONSTANT_InterfaceMethodref_info هو 11، رمزي مرجع إلى الطريقة الموجودة في علامة CONSTANT_NameAndType_info للواجهة علامة البت 12، وأسماء الحقول والأساليب، والمراجع الرمزية للأنواع
6) تمثل u2 access_flags معلومات الوصول الخاصة بالفئة أو الواجهة، كما هو موضح في الشكل التالي:
7) يمثل u2 this_class فهرس التجمع الثابت للفئة، ويشير إلى ثابت CONSTANT_Class_info في التجمع الثابت
8) يمثل u2 super_class فهرس الفئة الفائقة، مشيرًا إلى ثابت CONSTANT_Class_info في التجمع الثابت
9) تمثل u2 Interface_counts عدد الواجهات
10) تمثل واجهة u2[interface_counts] جدول الواجهة، حيث يشير كل عنصر فيه إلى ثابت CONSTANT_Class_info في التجمع الثابت
11) يمثل u2 field_count عدد متغيرات المثيل ومتغيرات الفئة الخاصة بالفئة
12) حقول field_info[fields_count] تمثل معلومات جدول الحقول، حيث يكون هيكل جدول الحقول كما هو موضح أدناه:
في الشكل أعلاه، يمثل access_flags تمثيل الوصول للحقل، على سبيل المثال، الحقل عام وخاص ومحمي. وما إلى ذلك، يمثل name_index اسم الحقل، ويشير إلى ثابت النوع CONSTANT_UTF8_info في التجمع الثابت، ويمثل descriptor_index واصف الحقل، والذي يشير أيضًا إلى ثابت النوع CONSTANT_UTF8_info في التجمع الثابت، ويمثل attributes_count عدد جداول السمات في جدول الحقول وجدول السمات، فهو هيكل قابل للتوسيع يستخدم لوصف الحقول والأساليب وسمات الفئة، تدعم الإصدارات المختلفة من جهاز Java الظاهري عددًا مختلفًا من جداول السمات.
13) يمثل u2methods_count عدد جداول الطريقة
14) يمثلmethod_info جدول الطريقة. الهيكل المحدد لجدول الطريقة كما هو موضح في الشكل أدناه:
من بينها، يمثل Access_flags تمثيل الوصول للطريقة، ويمثل name_index فهرس الاسم، ويمثل descriptor_index واصف الطريقة، وتتشابه attributes_count وattribute_info مع جداول السمات في جدول الحقول، باستثناء السمات الموجودة في جدول السمات يختلف جدول الحقل عن جدول الطريقة، على سبيل المثال، تمثل سمة Code في جدول الطريقة رمز الطريقة، ولكن لا توجد سمة Code في جدول الحقل. سيتم مناقشة عدد السمات الموجودة في فئة محددة لاحقًا عندما ننظر إلى جدول السمات في بنية ملف الفئة.
15) يمثل attribute_count عدد جداول السمات. عندما يتعلق الأمر بجداول السمات، نحتاج إلى توضيح النقاط التالية:
يوجد جدول السمات في نهاية بنية ملف الفئة، في جدول الحقل وجدول الطريقة وسمة الكود. وهذا يعني أن جدول السمات يمكن أن يكون موجودًا أيضًا في جدول السمات. سمات مختلفة لها أطوال مختلفة
بعد وصف تركيبة كل عنصر في بنية ملف الفئة أعلاه، نستخدم مثالًا عمليًا لشرح المحتوى التالي.
انسخ رمز الكود كما يلي:
package com.ejushang.TestClass;
الطبقة العامة TestClass تنفذ Super{
نهائي ثابت خاص int staticVar = 0;
مثيل int الخاصVar=0;
طريقة المثيل العام int (int Param) {
إرجاع المعلمة+1;
}
}
واجهة سوبر { }
يظهر في الشكل أدناه البنية الثنائية لـ TestClass.class المتوافقة مع TestClass.java التي تم تجميعها من خلال javac لـ jdk1.6.0_37:
بعد ذلك، سنقوم بتحليل تدفق البايتات في الشكل أعلاه بناءً على بنية ملف الفئة المذكورة سابقًا.
1) الرقم السحري <br/>من بنية ملف Class، نعلم أن أول 4 بايتات هي الرقم السحري في الصورة أعلاه، المحتوى من العنوان 00000000h-00000003h هو الرقم السحري من الصورة أعلاه. يمكننا معرفة الرقم السحري لملف الفصل وهو 0xCAFEBABE.
2) أرقام الإصدارات الرئيسية والثانوية <br/> البايتات الأربع التالية هي أرقام الإصدارات الرئيسية والثانوية من الشكل أعلاه، يمكننا أن نرى أن الأرقام المقابلة من 00000004h-00000005h هي 0×0000، وبالتالي فإن الإصدار الثانوي للفئة. هو 0×0000، والمحتوى المقابل من 00000006h-00000007h هو 0×0032، وبالتالي فإن إصدار الإصدار الرئيسي من ملف الفئة هو 0×0032، وهو بالضبط الإصدار الرئيسي والثانوي المطابق للفئة التي تم تجميعها بواسطة jdk1.6.0 بدون المعلمة المستهدفة.
3) عدد التجمع الثابت <br/> تمثل البايتتان التاليتان عدد التجمع الثابت من 00000008h-00000009h من الشكل أعلاه، يمكننا أن نعرف أن قيمته هي 0×0018، وهو 24 بالنظام العشري، ولكن بالنسبة إلى. يجب توضيح عدد التجمعات الثابتة. عدد التجمعات الثابتة هو Constant_pool_count-1 والسبب في تقليله بمقدار واحد هو أن الفهرس 0 يعني أن عناصر البيانات في الفصل لا تشير إلى أي ثوابت في التجمع الثابت.
4) التجمع الثابت <br/> لقد قلنا أعلاه أن هناك أنواعًا مختلفة من الثوابت في التجمع الثابت. دعونا نلقي نظرة على الثابت الأول في TestClass.class. نحن نعلم أن كل ثابت يتم تمثيله بواسطة معرف علامة من النوع u1. نوع الثابت عند 0000000ah في الصورة أعلاه المحتوى هو 0x0A، والذي تم تحويله إلى النظام الثانوي هو 10. من الوصف أعلاه للنوع الثابت، يمكن ملاحظة أن الثابت ذو العلامة 10 هو Constant_Methodref_info، وبنية Constant_Methodref_info كما هو موضح في الشكل أدناه:
من بينها، يشير class_index إلى ثابت النوع CONSTANT_Class_info في التجمع الثابت. ويمكن ملاحظة من بنية الملف الثنائي لـ TestClass أن قيمة class_index هي 0×0004 (العنوان هو 0000000bh-0000000ch)، مما يعني أنه يشير إلى. الثابت الرابع .
يشير name_and_type_index إلى الثابت من النوع CONSTANT_NameAndType_info في التجمع الثابت. كما يتبين من الشكل أعلاه، قيمة name_and_type_index هي 0×0013، مما يعني أنها تشير إلى الثابت التاسع عشر في التجمع الثابت.
بعد ذلك، يمكنك استخدام نفس الطريقة للعثور على كافة الثوابت في التجمع الثابت. ومع ذلك، يوفر JDK أداة ملائمة تتيح لنا عرض الثوابت الموجودة في التجمع الثابت. يمكنك الحصول على جميع الثوابت الموجودة في التجمع الثابت من خلال javap -verbose TestClass. لقطة الشاشة كما يلي:
من الصورة أعلاه، يمكننا أن نرى بوضوح أن هناك 24 ثابتًا في تجمع الثوابت في TestClass. لا تنس الثابت 0، لأن الثابت 0 يستخدم للإشارة إلى أن عناصر البيانات في الفصل لا تشير إلى أي ثوابت في الفصل. تجمع ثابت. من التحليل أعلاه، نعلم أن أول طريقة تمثيل ثابتة لـ TestClass هي أن الثابت الرابع الذي يشير إليه class_index هو java/lang/Object، والقيمة الثابتة التاسعة عشرة التي يشير إليها name_and_type_index هي <init>:()V From It can نلاحظ هنا أن الثابت الأول الذي يمثل الطريقة يمثل طريقة إنشاء المثيل التي تم إنشاؤها بواسطة مترجم Java. يمكن تحليل الثوابت الأخرى في التجمع الثابت بنفس الطريقة. حسنًا، بعد تحليل التجمع الثابت، دعنا نحلل Access_flags بعد ذلك.
5) تمثل u2 access_flags معلومات الوصول حول الفئات أو الواجهات، على سبيل المثال، تمثل الفئة ما إذا كانت فئة أو واجهة، سواء كانت عامة أو ثابتة أو نهائية وما إلى ذلك. لقد تم ذكر معنى علامة الوصول المحددة من قبل، فلنلقي نظرة على علامة الوصول الخاصة بـ TestClass. علامة الوصول للفئة هي من 0000010dh-0000010e، والقيمة هي 0×0021 وفقًا لبتات العلم لأعلام الوصول المختلفة المذكورة سابقًا، يمكننا معرفة: 0×0021=0×0001|0×0020، أي، ACC_PUBLIC وACC_SUPER صحيحان، ACC_PUBLIC سهل الفهم، وACC_SUPER عبارة عن علامة سيتم حملها بواسطة الفئات المجمعة بعد jdk1.2.
6) يمثل u2 this_class قيمة فهرس الفئة، والذي يستخدم لتمثيل الاسم المؤهل بالكامل للفئة، وتكون قيمة فهرس الفئة كما هو موضح في الشكل أدناه:
كما يتبين بوضوح من الشكل أعلاه، قيمة فهرس الفئة هي 0×0003، وهو ما يتوافق مع الثابت الثالث للتجميع الثابت. من خلال نتيجة javap، نعلم أن الثابت الثالث هو ثابت من النوع CONSTANT_Class_info، من خلال. والتي يمكننا من خلالها معرفة التفاصيل الكاملة للفصل الدراسي، والاسم المؤهل هو: com/ejushang/TestClass /TestClass
7) تمثل u2 super_class قيمة الفهرس للفئة الأصلية للفئة الحالية، وتشير قيمة الفهرس إلى ثابت من النوع CONSTANT_Class_info في التجمع الثابت، وتكون قيمة الفهرس للفئة الأصلية كما هو موضح في الشكل أدناه 0×0004. تحقق من الثوابت الأربعة الأولى للتجميع الثابت، ويمكن ملاحظة أن الاسم المؤهل بالكامل للفئة الأصلية لـ TestClass هو: java/lang/Object.
8) يمثل عدد الواجهات والواجهات[interfaces_count] عدد الواجهات وكل واجهة محددة عدد الواجهات والواجهات الخاصة بـ TestClass كما هو موضح في الشكل أدناه، حيث يعني 0×0001 أن عدد الواجهات هو 1، و0×. 0005 يعني فهرس الواجهة في قيمة التجمع الثابت، ابحث عن الثابت الخامس في التجمع الثابت، نوعه CONSTANT_Class_info، وقيمته هي: com/ejushang/TestClass/Super
9) field_count وfield_info ، يمثل field_count عدد جداول field_info في الفئة، ويمثل field_info متغيرات الحالة ومتغيرات الفئة. وتجدر الإشارة هنا إلى أن field_info لا يتضمن الحقول الموروثة من بنية الفئة الأصلية field_info كما هو موضح في الشكل أدناه:
من بينها، يمثل Access_flags علامة الوصول للحقل، مثل عام، خاص، محمي، ثابت، نهائي، إلخ. قيمة Access_flags كما هو موضح في الشكل أدناه:
من بينها، name_index وdescriptor_index كلاهما قيم فهرس للتجميع الثابت، والتي تمثل على التوالي اسم الحقل واصفه. من السهل فهم اسم الحقل، ولكن كيفية فهم واصف مجال؟ في الواقع، في مواصفات JVM، يتم تحديد واصفات الحقل كما هو موضح في الشكل التالي:
من بينها، يجب على الجميع الانتباه إلى السطر الأخير من الصورة أعلاه، وهو يمثل واصف مصفوفة أحادية البعد. سيكون واصف السلسلة [] [] هو [[ Ljava/lang/String، ووصف int[][] الرمز هو [[I. يمثل attributes_count وattributes_info التاليين عدد جداول السمات وجداول السمات على التوالي. لنأخذ TestClass أعلاه كمثال ونلقي نظرة على جدول الحقول الخاص بـ TestClass.
أولاً، دعونا نلقي نظرة على عدد الحقول. عدد الحقول في TestClass كما هو موضح في الشكل أدناه:
كما يتبين من الصورة أعلاه، يحتوي TestClass على حقلين، وبالنظر إلى الكود المصدري لـ TestClass، يمكننا أن نرى أن هناك بالفعل حقلين فقط الخاص int staticVar، والذي يكون التمثيل الثنائي في ملف Class كما هو موضح أدناه:
من بينها، يمثل 0x001A علامة الوصول. من خلال النظر إلى جدول Access_flags، يمكننا أن نعرف أنه ACC_PRIVATE، وACC_STATIC، وACC_FINAL، ويمثل 0x0006 و0x0007 الثوابت السادسة والسابعة على التوالي بالنظر إلى التجمع الثابت، يمكننا أن نعرف أن قيمها هي: staticVar وI، حيث staticVar هو اسم الحقل وI هو واصف الحقل. من خلال شرح الواصفات أعلاه، ما أصفه هو متغير من النوع int. بعد ذلك، يمثل 0×0001 عدد جداول السمات في جدول حقل staticVar، ويمكن ملاحظة أن هناك جدول سمات واحد مطابق إلى الحقل staticVar، يمثل 0×0008 الثابت الثامن في التجمع الثابت، وبالنظر إلى التجمع الثابت، يمكنك أن ترى أن هذه السمة هي سمة ConstantValue، وتنسيق سمة ConstantValue كما هو موضح في الشكل أدناه:
من بينها، يعبر attribute_name_index عن فهرس التجمع الثابت لاسم السمة. في هذا المثال، يكون ConstantValue. طول attribute_length الخاص بـ ConstantValue هو 2، ويمثل ConstantValue_index المرجع في التجمع الثابت ×0009. يمكنك عرض الثابت التاسع، وهو يمثل ثابتًا من النوع CONSTANT_Integer_info وقيمته 0.
بعد قولي هذا، الخاص الثابت النهائي int staticVar = 0، فلنتحدث عن الخاص int exampleVar = 0 لـ TestClass. في هذا المثال، يكون التمثيل الثنائي لـ exampleVar كما هو موضح في الشكل أدناه:
من بينها، 0x0002 يعني أن علامة الوصول هي ACC_PRIVATE، 0x000A تعني اسم الحقل، الذي يشير إلى الثابت العاشر في التجمع الثابت، يمكنك معرفة أن اسم الحقل هوinstanceVar، و 0× يمثل 0007 واصف الحقل، الذي يشير إلى الثابت السابع في التجمع الثابت، وبالنظر إلى التجمع الثابت، يمكنك معرفة أن الثابت السابع هو I، وهو ما يمثل نوع المثيلVar عدد جداول السمات هو 0. .
10)methods_count وmethods_info ، حيث يمثلmethods_count عدد الطرق، وmethods_info يمثل جدول الطريقة، حيث تكون بنية جدول الطريقة كما هو موضح في الشكل أدناه:
كما يتبين من الشكل أعلاه، فإن بنياتmethod_info وfield_info متشابهة جدًا، وجميع بتات العلم وقيم Access_flag في جدول الطريقة كما هو موضح في الشكل أدناه:
من بينها، يمثل name_index وdescriptor_index اسم الطريقة وواصفها، وهما فهرسان يشيران إلى التجمع الثابت على التوالي. نحن هنا بحاجة إلى شرح بنية واصف الطريقة هي: (قائمة المعلمات) القيمة المرجعة. على سبيل المثال، واصف int exampleMethod(int param) هو: (I) I، مما يعني أنه يحتوي على int. معلمة النوع والقيمة المرجعة هي أيضًا طريقة من النوع int. التالي هو عدد السمات وجدول السمات. على الرغم من أن جدول الطريقة وجدول الحقول يحتويان على عدد السمات وجدول السمات، إلا أن السمات التي يحتويان عليها هي. مختلف. بعد ذلك، دعونا نلقي نظرة على التمثيل الثنائي لجدول الطريقة باستخدام TestClass. أولاً، دعونا نلقي نظرة على عدد جداول الطريقة. لقطة الشاشة هي كما يلي:
كما يتبين من الشكل أعلاه، فإن عدد جداول الطريقة هو 0×0002، مما يعني أن هناك طريقتين. بعد ذلك، دعونا نحلل الطريقة الأولى أولاً، وهي الطريقة access_flag وname_index وdescriptor_index. لقطة الشاشة هي كما يلي:
من الشكل أعلاه، يمكننا أن نعرف أن قيمة Access_flags هي 0×0001، ومن الوصف أعلاه لعلامة Access_flags، يمكننا أن نرى أن قيمة Access_flags للطريقة هي ACC_PUBLIC، وname_index هو 0x000B. الثابت الحادي عشر، مع العلم أن اسم الطريقة هو <init>، 0x000C يعني أن descriptor_index يعني الثابت الثاني عشر في تجمع الثابت، وقيمته ()V، مما يعني أن الطريقة <init> لا تحتوي على معلمات وقيمة إرجاع. في الواقع، هذا هو المترجم الذي تم إنشاؤه تلقائيًا لطرق إنشاء المثيل. يشير 0×0001 التالي إلى أن جدول الطريقة الخاص بالطريقة <init> يحتوي على سمة واحدة. لقطة شاشة السمة هي كما يلي:
كما يتبين من الشكل أعلاه، فإن الثابت في التجمع الثابت المقابل لـ 0x000D هو الكود، الذي يمثل سمة الكود الخاصة بهذه الطريقة، لذلك يجب على الجميع هنا أن يفهموا أن رموز الطريقة مخزنة في سمة الكود في السمة الجدول في جدول الطريقة لملف الفئة. بعد ذلك نقوم بتحليل سمة الكود. يظهر هيكل سمة الكود في الشكل أدناه:
من بينها، يشير attribute_name_index إلى الثابت الذي تكون قيمته Code في التجمع الثابت، ويشير طول attribute_length إلى طول جدول سمات Code (تجدر الإشارة إلى أن الطول لا يشمل طول 6 بايت من attribute_name_index وattribute_length ).
يمثل max_stack الحد الأقصى لعمق المكدس. يخصص الجهاز الظاهري عمق المعاملات في إطار المكدس بناءً على هذه القيمة في وقت التشغيل، ويمثل max_locals مساحة التخزين لجدول المتغير المحلي.
وحدة max_locals هي فتحة، وهي أصغر وحدة للجهاز الظاهري لتخصيص الذاكرة للمتغيرات المحلية في وقت التشغيل، تشغل أنواع البيانات التي لا تتجاوز أنواع 32 بت، مثل البايت، والشار، والكثافة السكانية، وما إلى ذلك 1. فتحة، في حين مزدوجة وطويلة يحتاج نوع البيانات 64 بت إلى تخصيص فتحتين بالإضافة إلى ذلك، فإن قيمة max_locals ليست مجموع الذاكرة المطلوبة لجميع المتغيرات المحلية، لأنه يمكن إعادة استخدام الفتحات عندما يتجاوز المتغير المحلي نطاقه سيتم إعادة استخدام الفتحة المشغولة.
يمثل code_length عدد تعليمات الكود الثانوي، ويمثل الكود تعليمات الكود الثانوي. من الشكل أعلاه، يمكننا معرفة أن نوع الكود هو u1، وقيمة النوع u1 هي 0×00-0xFF، والعلامة العشرية المقابلة هي 0-. 255. حاليًا، حددت مواصفات الجهاز الظاهري أكثر من 200 تعليمات.
يمثل Exception_table_length و Exception_table على التوالي معلومات الاستثناء المقابلة للطريقة.
تمثل attributes_count وattribute_info عدد السمات وجدول السمات في سمة Code على التوالي، ويمكن ملاحظة أن جدول السمات مرن جدًا في بنية ملف Class ويمكن أن يكون موجودًا في ملف Class وجدول الطريقة والحقل سمة الجدول والكود.
بعد ذلك، نواصل تحليل المثال أعلاه من لقطة شاشة لسمة Code لطريقة init أعلاه، يمكننا أن نرى أن طول جدول السمات هو 0×00000026، وقيمة max_stack هي 0×0002، وقيمة max_stack هي 0×0002. max_locals هو 0 × 0001، وطول code_length هو 0x0000000A، ثم 00000149h- 00000152h هو رمز بايت. بعد ذلك، طول Except_table_length هو 0×0000، وقيمة attribute_count هي 0×0001. قيمة 00000157h-00000158h هي 0x000E، وهو ما يمثل اسم السمة في التجمع الثابت للحصول على الرقم الرابع عشر، قيمة الثابت هي LineNumberTable، LineNu يتم استخدام mberTable لوصف المراسلات بين رقم سطر التعليمات البرمجية المصدر لـ Java ورقم سطر الرمز الثانوي، وهي ليست سمة مطلوبة في وقت التشغيل. إذا قمت بإلغاء إنشاء هذه المعلومات من خلال معلمة برنامج التحويل البرمجي -g:none، فسيكون التأثير الأكبر عند حدوث استثناء، لا يمكن عرض رقم سطر الخطأ على المكدس، ولا يمكن تعيين نقاط التوقف وفقًا للكود المصدر أثناء التصحيح. بعد ذلك، دعنا نلقي نظرة على بنية LineNumberTable، كما هو موضح أدناه:
من بينها، تم ذكر attribute_name_index أعلاه ويمثل فهرس التجمع الثابت، ويمثل attribute_length طول السمة، ويمثل جدولي start_pc وline_number رقم السطر من الكود الثانوي ورقم السطر من الكود المصدري. دفق البايت الخاص بخاصية LineNumberTable في هذا المثال هو كما هو موضح أدناه:
بعد تحليل الطريقة الأولى لـ TestClass أعلاه، يمكننا تحليل الطريقة الثانية لـ TestClass بنفس الطريقة، لقطة الشاشة كما يلي:
من بينها، Access_flags هو 0×0001، name_index هو 0x000F، وdescriptor_index هو 0×0010، من خلال النظر إلى التجمع الثابت، يمكنك معرفة أن هذه الطريقة هي طريقة int exampleMethod العامة (int param). من خلال طريقة مشابهة لما سبق، يمكننا معرفة أن خاصية Code الخاصة بـ exampleMethod هي كما هو موضح في الشكل أدناه:
أخيرًا، دعونا نحلل سمات ملف Class. من 00000191h إلى 00000199h هو جدول السمات في ملف Class، حيث يمثل 0×0011 اسم السمة. بالنظر إلى التجمع الثابت، يمكننا معرفة أن اسم السمة هو SourceFile دعونا نلقي نظرة على بنية SourceFile كما هو موضح في الشكل:
من بينها، attribute_length هو طول السمة، ويشير sourcefile_index إلى الثابت في التجمع الثابت الذي تمثل قيمته اسم ملف التعليمات البرمجية المصدر، في هذا المثال، لقطة شاشة لسمة SourceFile هي كما يلي:
من بينها، attribute_length هو 0×00000002، مما يعني أن الطول هو 2 بايت، وقيمة sourcefile_index هي 0×0012. وبالنظر إلى الثابت الثامن عشر في التجمع الثابت، يمكنك معرفة أن اسم ملف التعليمات البرمجية المصدر هو TestClass .جافا
أخيرًا، أتمنى أن يتمكن الأصدقاء المهتمون بالتكنولوجيا من التواصل أكثر. ويبو شخصي: (http://weibo.com/xmuzyq)