יום שישי, 28 ביוני 2019

זהירות! רקורסיה הדדית בין מחלקות (Java)

זה לא מפתיע, גם ביצירה של מחלקות יש להיזהר מ-Deadlock.
נתבונן בקוד הבא:

class A {
    final static B b;
    static {
        System.out.println("In A static block");    
        b = new B();
    }

    A() {
        if (b != null) {
            System.out.println("B is: " + b);
        } else {
            System.out.println("the static block was not completed, "
                    + "inspite of we are in the constructor!!!");
        }
    }
}

class B {
    final static A a;
    static {
        System.out.println("In B static block");   
        a = new A();
    }

    B() {
    }

    @Override
    public String toString() {
        return "I am B";
    }
}
public class Program {

    public static void main(String[] args) {
        new A();
        new A();
    }
}

OUTPUT:
In A static block
In B static block
the static block was not completed, inspite of we are in the constructor!!!
B is: I am B
B is: I am B


מה קורה פה?
המחלקות A ו-B כל אחת מהן מגדירה ב-static block שלה משתנה מסוג המחלקה השניה.
תאורטית הייתה אמורה להיות כאן רקורסיה הדדית, או Deadlock, אבל ה-Class-Loader יודע "לברוח" מהדברים האלו ע"י שימוש בערכי ברירת מחדל למשתני המחלקות.

בשפות אחרות יכולות להיות תוצאות מוזרות ולא צפויות לבעיה הזאת. חפשו static initialization order fiasco למידע על ++C.
למצוא את  "הזוג הבעייתי" יכול להיות סיוט בדיבאג של פרויקט גדול... נסו להזהר ככל האפשר.






בהצלחה.

אין תגובות:

הוסף רשומת תגובה