0

Lets say we have the following classes and two threads t1,t2.

public class A {
        static String str = "abc";

        static {
          B.bMeth();
        }

        static void aMeth() {
            System.out.println("A::meth()");
            str = "abc2";
        }

        static void aSomeMeth() {}
    }

public class B {

        static {
            A.aMeth();
        }

        static void bMmeth() {}
        static void bSomeMeth() {}
    }

Following is the sequence for the deadlock to occur:

1) t1 executes A.aSomeMeth() which acquires lock on class loading for A.

2) t2 executes B.bSomeMeth() which acquires lock on class loading for B.

3) t1 proceeds to execute B.bMeth() and requires lock for B while holding lock of A.

4) t2 proceeds to execute A.aMeth() and requires lock for A while holding lock for B.

This causes a dead lock. But in my case t2 actually enters aMeth() and is blocked while accessing the static member str. So I want to know if its possible for a thread to enter a static method before initialization in special conditions.

In my test runs, t2 was always blocked at A.aMeth() as expected, so could there be any corner cases where it can enter it and be blocked on str, JIT optimizations like method inlineing etc.

Hrishikesh
  • 25
  • 6

1 Answers1

1

No, a class can only be initialized once, by exactly one thread. If another thread accesses the same class, this one will block while initialization completes.

Holger
  • 285,553
  • 42
  • 434
  • 765
loonytune
  • 1,775
  • 11
  • 22
  • Right, so ideally t2 should be blocked on `aMeth`() but can JIT do method inlining for `aMeth`(), so static block of B looks like public class B { static { System.out.println("A::meth()"); A.str = "abc2"; } } and so t2 will be blocked on the line accessing the static instance `str`. Now taking a thread stack trace, it will apear t2 is inside the method `aMeth`(). – Hrishikesh Dec 12 '17 at 10:27
  • no, this cannot happen for several reasons: when a class is being loaded, the loading code is still being interpreted. The JIT code does not contain any handling for classloading, because it relies that all initialization stuff is already done. Otherwise it would impede a lot of optimizations. Also, a JIT must (!) maintain the same behavior of the code. – loonytune Dec 13 '17 at 08:55
  • I rephrased your answer a bit. “at a time” misleadingly creates the impression that this process could happen more than once, just by one thread “at a time”. Further, I changed “loaded” to “initialized”, as loading and initialization are two different things, not necessarily done by the same thread, and the question is about the initialization (but both things can happen only once). – Holger Feb 20 '18 at 14:00