Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class initialization and synchronized class method

In my application, there is a class like below:

public class Client {
    public synchronized static print() {
        System.out.println("hello");
    }

    static {
        doSomething(); // which will take some time to complete
    }
}

This class will be used in a multi thread environment, many threads may call the Client.print() method simultaneously. I wonder if there is any chance that thread-1 triggers the class initialization, and before the class initialization complete, thread-2 enters into print method and print out the "hello" string?

I see this behavior in a production system (64 bit JVM + Windows 2008R2), however, I cannot reproduce this behavior with a simple program in any environments.

In Java language spec, section 12.4.1 (http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html), it says:

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.
  • T is a class and a static method declared by T is invoked.
  • A static field declared by T is assigned.
  • A static field declared by T is used and the reference to the field is not a compile-time constant (§15.28). References to compile-time constants must be resolved at compile time to a copy of the compile-time constant value, so uses of such a field never cause initialization.

According to this paragraph, the class initialization will take place before the invocation of the static method, however, it is not clear if the class initialization need to be completed before the invocation of the static method. JVM should mandate the completion of class initialization before entering its static method according to my intuition, and some of my experiment supports my guess. However, I did see the opposite behavior in another environment. Can someone shed me some light on this?

Any help is appreciated, thanks.

like image 438
nybon Avatar asked Jan 07 '11 07:01

nybon


People also ask

What are synchronized methods?

Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods.

What is the difference between a synchronized block and a synchronized method?

Key DifferencesA synchronized method assigns an object-level or class-level corresponding lock. And synchronized block assign a lock to the object based on the parameter.

What does it mean if a class is synchronized?

Synchronized blocks or methods prevents thread interference and make sure that data is consistent. At any point of time, only one thread can access a synchronized block or method (critical section) by acquiring a lock.

Can two synchronized methods in same class?

You cannot call two synchronized methods of a class on the same object. This is the use of synchronization. If you can call two synchronized methods on the same object then there is a chance of corruption of the state of the object. Synchronization helps you to avoid this....


2 Answers

My understanding of the quoted text is that the class initialization process is completed (will be initialized) before a static method declared by T is invoked.

will be initialized implies that the initialization process has been started and has terminated.

So it shouldn't be possible (to my understanding) that, while the static initializer is executed because Thread A called print, another Thread already can call print.

Chapter 12.4.2 of the JLS describes the detailed initialization procedure, which takes care of initializing classes in a multithreaded environment.

like image 150
Andreas Dolk Avatar answered Sep 21 '22 21:09

Andreas Dolk


If your "multi thread environment" uses multiple class loaders to load your Client class it would be possible for you to get mulitple Client instances, each one of which would run the static initialiser prior to running any Client.print() calls. You would see something like

doSomething
hello
doSomething
hello
hello
hello

I have some sample code which shows this but the current version is a little fiddly to run. If you want I can clean it up and post it.

like image 31
Michael Rutherfurd Avatar answered Sep 23 '22 21:09

Michael Rutherfurd