Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incorrect lazy initialization

Tags:

java

findbugs

People also ask

What is lazy initialization in Java?

In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed. It is a kind of lazy evaluation that refers specifically to the instantiation of objects or other resources.

Is lazy initialization good?

Lazy initialization of an object means that its creation is deferred until it is first used. (For this topic, the terms lazy initialization and lazy instantiation are synonymous.) Lazy initialization is primarily used to improve performance, avoid wasteful computation, and reduce program memory requirements.

What is lazy initialization Android?

Lazy Initialization lazy() is a function that takes a lambda and returns an instance of lazy which can serve as a delegate of lazy properties upon which it has been applied. It has been designed to prevent unnecessary initialization of objects. Lazy can be used only with non-NULLable variables.

What is a lazy Singleton?

Singleton and Lazy<T> The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects. The term comes from the mathematical concept of a singleton.


Findbug is referencing a potential threading issue. In a multi thread environment, there would be potential for your singleton to be created more than once with your current code.

There is a lot of reading here, but it will help explain.

The race condition here is on the if check. On the first call, a thread will get into the if check, and will create the instance and assign it to 'instance'. But there is potential for another thread to become active between the if check and the instance creation/assignment. This thread could also pass the if check because the assignment hasn't happened yet. Therefore, two (or more, if more threads got in) instances would be created, and your threads would have references to different objects.


Your code is slightly more complex than needed which might be why it's confused.

Edit: It's definitely the threading issue as the others posted but thought I'd post the double lock check implementation here for reference below:

private static final Object lock = new Object();
private static volatile Object instance; // must be declared volatile

public static Object getInstance() {
    if (instance == null) { // avoid sync penalty if we can
        synchronized (lock) { // declare a private static Object to use for mutex
            if (instance == null) {  // have to do this inside the sync
                instance = new Object();
            }
        }
    }

    return instance;
}

NOTE: JohnKlehm's double lock checking solution is better. Leaving this answer here for historical reasons.

It should actually be

public synchronized static Object getInstance() {
    if (instance == null) {
        instance = new Object();
    }

    return instance;
}

You need to put a lock around instantiation to make this correct

LI: Incorrect lazy initialization of static field (LI_LAZY_INIT_STATIC)

This method contains an unsynchronized lazy initialization of a non-volatile static field. Because the compiler or processor may reorder instructions, threads are not guaranteed to see a completely initialized object, if the method can be called by multiple threads. You can make the field volatile to correct the problem. For more information, see the Java Memory Model web site.


Thanks to John Klehm for posted sample

also may try to assign object instance in sychronised block directly

synchronized (MyCurrentClass.myLock=new Object())

i.e.

private static volatile Object myLock = new Object();

public static Object getInstance() {
    if (instance == null) { // avoid sync penalty if we can
        synchronized (MyCurrentClass.myLock**=new Object()**) { // declare a private static Object to use for mutex
            if (instance == null) {  // have to do this inside the sync
                instance = new Object();
            }
        }
    }

    return instance;

}