سؤال

في جافا هذا هو الحال:

public void method() {
  if (condition) {
    Object x = ....;
  }
  System.out.println(x); // Error: x unavailable
}

ما أتساءل هو هذا: هل حقيقة ذلك x يقتصر على نطاق if-أيمة مجرد ميزة من برنامج التحويل البرمجي Java ، أو هو x تمت إزالته بالفعل من المكدس بعد if-بيان؟

هل كانت مفيدة؟

المحلول

لا ، لا تحصل كتل التعليمات البرمجية على إطار مكدس منفصل ، استخدم أحد الطريقة المحيطة.

ومع ذلك ، بمجرد وجود نطاق يترك المتغير ، يمكن إعادة استخدام مكانه في إطار المكدس الحالي للمتغيرات الأخرى.

تم وصف هيكل واستخدام إطار المكدس في مواصفات الجهاز الافتراضي Java § 3.6 إطارات:

يتم إنشاء إطار جديد في كل مرة يتم فيها استدعاء طريقة. يتم تدمير الإطار عند اكتمال استدعاء الطريقة ، سواء كان هذا الانتهاء طبيعيًا أو مفاجئًا (يلقي استثناءً غير معطل).

هذا بالتأكيد يحدد العلاقة 1: 1 بين دعوات الطريقة والإطارات.

نصائح أخرى

الكتل هي جزء من لغة جافا (وهي أ لغة البرمجة المنظمة) في حين أنها ليست جزءًا من رمز bytecode المترجم (وهو أمر غير منظمة لغة).

تحدد مواصفات الطريقة في ملف الفئة عدد المتغيرات المحلية التي تستخدمها الطريقة في المجموع ، أعلى من القائمة الفعلية للتعليمات. ولكن حيث لا يمكن استنتاج الكتل مرة واحدة في رمز Java من رمز bytecode.

بادئ ذي بدء ، يتم تخزين متغيرات Bytecode في فتحات متغيرة وفتحات متغيرة وليس على المكدس. يمكن إعادة استخدام الفتحة بواسطة متغير آخر ، ولكن ليس من الممكن إزالة القيمة من الفتحة المتغيرة.

على سبيل المثال ، الفئة التالية

  public class A {
    public void method(boolean condition) {
 6    if (condition) {
 7      Object x = "";
 8      System.out.println(x);
 9    }
10    System.out.println(condition);
    }
  }

تم تجميعه في هذا الرمز البريطاني:

// class version 50.0 (50)
public class A {
  ...

  // access flags 0x1
  public method(Z)V
   L0
    LINENUMBER 6 L0
    ILOAD 1
    IFEQ L1
   L2
    LINENUMBER 7 L2
    LDC ""
    ASTORE 2
   L3
    LINENUMBER 8 L3
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 2
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   L1
    LINENUMBER 10 L1
   FRAME SAME
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ILOAD 1
    INVOKEVIRTUAL java/io/PrintStream.println (Z)V
   L4
    LINENUMBER 11 L4
    RETURN
   L5
    LOCALVARIABLE this LA; L0 L5 0
    LOCALVARIABLE condition Z L0 L5 1
    LOCALVARIABLE x Ljava/lang/Object; L3 L1 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

لاحظ أن المتغير X الذي تم إنشاؤه في السطر 7 يتم تخزينه في الفتحة المتغيرة 2 ، والتي لا تزال متوفرة في رمز bytecode المقابل للخط 10.

لا توجد مواصفات حول كيفية تجميع لغة Java في رمز Bytecode آخر ، ثم بعض الأمثلة على كيفية تجميع بعض بنيات اللغة بشكل صحيح. ومع ذلك ، يُسمح لمجمول جافا بالقضاء على المتغيرات غير المستخدمة. على سبيل المثال ، إذا تم تعيين x ، ولكن لم يتم استخدامه في أي مكان ، يُسمح للمترجم بإسقاط هذا الرمز. وبالمثل ، فإن برنامج التحويل البرمجي يدخل جميع الثوابت الثابتة.

نعم ، تتم إزالتها حقًا من المكدس مما يجعل الفتحة التي كانت تشغلها "X" قابلة لإعادة الاستخدام من قبل بعض المتغيرات المحلية الأخرى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top