Accessing uninitialized static field in Java

I am grateful to this answer for this idea.

The following code compiles, but of course it shouldn't. It uses the value x

before initializing it. If you remove the classifier StaticAssign.

, then it no longer compiles.

public class StaticAssign {

    public static final int x;

    static {
        System.out.println(StaticAssign.x);
        x = 5;
    }

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

}

      

On my machine, this prints consistently 0

. If I change the type x

to String

, it prints consistently null

.

The question is: will it print 0

or null

, or can it access uninitialized memory and print something else?

And even if this code goes through the compiler, why isn't it picked up by the JVM?

Is there a way to do nasty things based on this?

+3


source to share


2 answers


In fact, it was initialized. Variables in the global scope are automatically initialized. Object type variables will be initialized to null primitive, since int will be initialized to 0. A variable declared not in the global scope must be initialized, i.e. declared in the method. Another problem is declaring it as final

, which tells the compiler to explicitly initialize it. So by adding x=5

, you work around the compiler error by stating that it must be explicitly initialized. When you access it before this line at runtime, it is initialized to 0, like any other primitive int variable in the global scope.



+2


source


It has to do with how the classes are loaded.

First, the class definition is loaded StaticAssign

and the fields are initialized with default values:

StaticAssign.x = 0;

      

Then the initialization block is executed.

System.out.println(StaticAssign.x);
x = 5;

      

There is a link to the StaticAssign.x

current class. Since attempts at recursive initialization are simply ignored, the value x

is still 0

.

It means that:



System.out.println(StaticAssign.x)

      

valid because it StaticAssign.x

is a reference to a field of the allready loaded class.

But if yo do:

System.out.println(x)   

      

This x

is a reference to the final uninitialized field.

On the other hand, you will never access uninitialized memory. When the class definition is loaded, the variables are initialized to their default values, before the initialization block is executed.

EDIT: There is a nice video "Elvis Lives Again" from Java Puzzlers that shows this much better than I can explain

0


source







All Articles