0

As part of JVM Loading, Linking and Initalizing, When the

  1. static fields
  2. final static fields

in Class

  1. allocating in memory
  2. init as default value
  3. init as real value

In the case of the static final variables, I think that everything happens in the Loading step, because all values are already in Constant Pool.

But I can not figure out what's going on with the static fields. In principle, in the written documantation that they are initialized with default value in the Preparation step.

Preparation involves creating the static fields for a class or interface and initializing such fields to their default values (§2.3, §2.4). This does not require the execution of any Java Virtual Machine code; explicit initializers for static fields are executed as part of initialization (§5.5), not preparation.

But in this source (Class Variables paragraph) loading the static fields initialization occurs already in the Loading step. This makes sense because at the end of the loading step an instance of the class object is created, and it must contain room for the static fields.

Before a Java virtual machine uses a class, it must allocate memory from the method area for each non-final class variable declared in the class.

So I'd like to know what the right fact is in this case.

1
  • I can not figure out what's going on with the static fields what exactly ? Commented Feb 5, 2018 at 12:16

3 Answers 3

3

Generally, if there is some mismatch between the official specification and some article on the internet, you can safely assume that the specification has the last word and the article is wrong. This will serve you in 99.99% of all cases.

That’s especially true when it comes to the Java Virtual Machine, where articles notoriously mix up the steps of your question (“Loading, Linking, and Initializing”), and also regularly mix up formal steps and implementation details.

The article you’ve linked, does it wrong in several aspects:

  • Not every static final field is a compile-time constant. Only static final fields of primitive types or String are compile-time constants, if they are immediately initialized with a compile-time constant. Consider

    static final String CONSTANT1 = ""; // compile-time constant
    static final String CONSTANT2 = CONSTANT1; // compile-time constant
    // but
    static final String NO_CONSTANT1 = CONSTANT1.toString(); // not a constant expression
    static final String NO_CONSTANT2; // no initializer
    static {
        NO_CONSTANT2 = ""; // assignment in class initializer, valid, but not constant
    }
    static final BigInteger NO_CONSTANT3 = BigInteger.ONE; // neither primitive nor String
    
  • For compile time constants, every ordinary Java language read access is replaced by the constant value at compile-time, still, the identifiers exist and can be inspected via Reflection or accessed by byte code not generated from Java language source code. Whether the JVM treats constant fields specially, when it comes to their storage, is an implementation detail, but usually, implementors try to avoid special treatment, unless there’s a true benefit.

    The formal specification describes the constant variables as-if having a storage like any other variable, but of course, implementations may omit this, if they are capable of still retaining the mandated behavior (e.g. make the values available to Reflection).

    The initialization of both, constant and non-constant static variables is clearly specified as part of the Initialization (though not at the same time):

     

    1. Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC. Then, initialize each final static field of C with the constant value in its ConstantValue attribute (§4.7.2), in the order the fields appear in the ClassFile structure.

     9. Next, execute the class or interface initialization method of C.

    The “class or interface initialization method” is the method named <clinit> at the bytecode level, which contains all initializers of non-constant static fields as well as any code in static { … } blocks.

  • Class variables and the constant pool are different things. The constant pool contains the symbolic names of fields as well as values for compile-time constants (which, by the way, may include non-static fields as well).

    The values of the constant pool can be used to construct the actual runtime values, e.g. the byte sequence describing a string has to be converted to a reference to an actual String object and the primitive types may undergo Endianess conversions. When this processing happens as part of step 6 described in JVMS§5.5, as cited above, subsequent access to the field will consistently use the result of this process.

Sign up to request clarification or add additional context in comments.

Comments

0

My understanding is that the memory allocation is done during the preparation, and the execution of the initializers during initialization. This doesn't contradict either of the sources.

5 Comments

So after Loading and before Preparing we have a class object without its (static) fields? Maybe I do not understand the structure of the class object correctly. Maybe it has a list of fields that can be updated after creating the object?
@Baruch IMHO, preparation is part of the loading process
@Maurice_Perry preparation is part of Linking process
@Baruch yes, obviously
I think my question is completely wrong. class java.lang.Class contains class attribute lists, not the static variables, so there is no problem creating it before the static variables.
0

To be precise,

  • Instance variables will be stored on the heap.
  • local variables on the stack(in case of variable not a primitive[reference variable] reference variables live on stack and the object on heap ). Only method invocation and partial results will be stored in stack not the method itself.
  • Static variables and Methods(including static and Non Static) on the Method Area. Static methods (in fact all methods) as well as static variables are stored in the PermGen section , since they are part of the reflection data (class related data, not instance related).

For static variables, if you do not initialize a variable, default value would be stored before object preparation (JVM takes care of this) but for Final Static, you need to initialize the variable before the object is created i.e. when we try to create a new object calling the constructor, before the object is returned to the reference variable, value need to be initialized else it is a compile time error.

Answers to your questions:

  • Static variable in Java belongs to the class and initialized only once when the class is invoked (if not initialized - Lazy Initialization).

  • Static final variable is initialized at the time of class loading in the method Area, as it is already initialized in the code (early initialization).

  • There wont be any change in the allocating in memory for static and final static.

    public class Object {
    
        public static final int i;
        static{
            i=0; // comment this line gives you compile time error
        }
        /**
         * @param args
         */
        public static void main(String[] args) {
    
        }
    }
    

5 Comments

You did not consider Loading and Preparing.
what do you mean by loading and preparing...when do the static variables be loaded and prepared?
“PermGen” is an implementation detail and starting with Java 8 (of the common HotSpot implementation), there is no PermGen space anymore. Further, static variables are not initialized “at the start of the execution”, but at precise points mandated by the specification. These precise points are the topic of this question.
Hi @Holger, I feel that , if static variables are not initialized with a variable, they would be initialized when the class is invoked in the code (Lazy initialization) and for a final static as the variable would be initialized, it is initialized during the method loading in Method Area. Is that what you are looking for?
Well, yes, that’s the topic. However, the correct answer is that static variables are initialized when the class is initialized, and it is precisely specified in JLS §12.4.1. when a class will be initialized.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.