This is a very wide-spread enum singleton code:
public enum enumClazz{
INSTANCE
enumClazz(){
//do something
}
}
and a bunch of places said it is a lazy initialization. But I am confused after I read Chapter 7 of 'Inside the Java Virtual Machine' -- The Lifetime of a Type:
The Java virtual machine specification gives implementations
flexibility in the timing of class and interface loading and linking,
but strictly defines the timing of initialization. All implementations
must initialize each class or interface on its first active use. The
following six situations qualify as active uses:
A new instance of a class is created (in bytecodes, the execution of a new instruction. Alternatively, via implicit creation,
reflection, cloning, or deserialization.)
The invocation of a static method declared by a class (in bytecodes, the execution of an invokestatic instruction)
The use or assignment of a static field declared by a class or interface, except for static fields that are final and initialized by
a compile-time constant expression (in bytecodes, the execution of a
getstatic or putstatic instruction)
The invocation of certain reflective methods in the Java API, such as methods in class Class or in classes in the java.lang.reflect
package
The initialization of a subclass of a class (Initialization of a class requires prior initialization of its superclass.)
The designation of a class as the initial class (with the main()< method) when a Java virtual machine starts up
The third point with bold style clarify that if the field is static final, the initialization of the field is happened at compile-time. Likewise, the INSTANCE in enumClazz is implicitly equal to public static final and comply with the third point.
Can someone correct me if my understanding is wrong?
enum instance fields are not "initialized by a compile-time constant expression". They
can't be, because only String and primitive types are possible types for a compile-time constant expression.
That means that the class will be initialized when INSTANCE is first accessed (which is exactly the desired effect).
The exception in the bold text above exists, because those constants (static final fields initialized with a compile-time constant expression) will effectively be inlined during compilation:
class A {
public static final String FOO = "foo";
static {
System.out.println("initializing A");
}
}
class B {
public static void main(String[] args) {
System.out.println(A.FOO);
}
}
Executing class B in this example will not initialize A (and will not print "initializing A"). And if you look into the bytecode generated for B you'll see a string literal with the value "foo" and no reference to the class A.
The third point with bold style clarify that if the field is 'static final', the initialzation of the field is happened at complie-time
Not exactly - it only applies to "static fields that are final and initialized by a compile-time constant expression":
static final String = "abc"; //compile time constant
static final Object = new Object(); //initialised at runtime
In your case, the singleton will be initialised when the enum class is loaded, i.e. the first time enumClazz is referenced in your code.
So it is effectively lazy, unless of course you have a statement somewhere else in your code that uses the enum.
Related
As part of JVM Loading, Linking and Initalizing, When the
static fields
final static fields
in Class
allocating in memory
init as default value
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.
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):
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.
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.
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) {
}
}
I have a class which contains:
a public, static inner enum
private constants referring to an int and to the enum
a private inner class
Referring to the enum constant from inside the inner class generates a synthetic accessor warning, but referring to the int constant does not.
Why is this? How can I prevent this warning without making the enum constant package scope or disabling the warning? (e.g. perhaps by making an explicit accessor?)
Code reproducing the problem:
public class Outer {
public static enum Bar {
A, B, C;
}
private static final int FOO = 0;
private static final Outer.Bar BAR = Outer.Bar.A;
private class Inner {
{
int foo = Outer.FOO; // just fine
Outer.Bar bar = Outer.BAR; // synthetic accessor method warning
}
}
}
The JLS requires that accesses to compile time constants be "inlined" into the consuming class, rather than leaving a symbolic reference to be resolved at link and run time. In particular, from JLS 13.1:
References to fields that are constant variables (§4.12.4) are
resolved at compile time to the constant value that is denoted. No
reference to such a field should be present in the code in a binary
file (except in the class or interface containing the field, which
will have code to initialize it).
In particular, this means that you class Inner doesn't have any trace of Outer.FOO in its compiled class file. Rather, the constant value 0 of FOO is directly compiled into Inner at compile time.
Synthetic access methods are (among other reasons) added to ease runtime access to private fields between nested classes - but in the case of FOO, the access is already resolved at compile time, so no method is needed.
Outer.BAR on the other hand, is not eligible for compile-time constant treatment - because objects other than certain String objects are not compile time constants per 15.28:
A compile-time constant expression is an expression denoting a value
of primitive type or a String that does not complete abruptly and is
composed using only the following...
An Enum is neither a primitive nor a String, so the special handling for compile-time constants doesn't apply, and a synthetic accessor method is generated.
I think to a common Singleton Design Pattern:
public class Singleton{
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
if(instance==null)
instance=new Singleton();
return instance;
}
}
as far as I know, costructors are NON static methods because they can use the context reference "this" (which is forbidden in static contexts). On the other hand, static members can access only static members.
So how is it possible that static member getInstance() is accessing the non static member constructor?
When you see an object creation like new Singleton() you must distinguish the new operator from the constructor code or to be more precise the initializer code.
The new operator is "like" a static method call. It doesn't need an instance of an object, because it creates one.
The constructor code is more "like" an instance method, except that it has no return type. But it can access the this reference.
At least you will see the difference when you dive into the generated bytecode. The new operator will lead to this bytecode instruction.
NEW yourpackage/Singleton
This instruction only creates the object in memory. See jvms-6.5.new
After the object is created it is initialized by executing the initializer code. In the bytecode it looks like:
INVOKESPECIAL yourpackage/Singleton.<init> ()V
The initializer code is more than only the constructor code. It invokes the super class's initializer and initializes instance fields.
Also see the java virtual machine specification 2.9
At the level of the Java Virtual Machine, every constructor written in the Java programming language (JLS §8.8) appears as an instance initialization method that has the special name . This name is supplied by a compiler. Because the name is not a valid identifier, it cannot be used directly in a program written in the Java programming language. Instance initialization methods may be invoked only within the Java Virtual Machine by the invokespecial instruction (§invokespecial), and they may be invoked only on uninitialized class instances. An instance initialization method takes on the access permissions (JLS §6.6) of the constructor from which it was derived
Constructors are not methods. Static methods are associated with a class, and non-static methods are associated with instances of that class. You cannot call non-static method from a static method because there is no instance associated with the static method. You can call constructors from static methods because constructors are associated with classes, not instances.
Constructors can use "this" reference only after the object is instantiated, i.e. after the constructor is called.
Consider sample code below
public class Test {
public static void main(String args[]) {
Test t = new Test();
Class c2 = Test.class;
System.out.println(c2);
}
}
Test.class statically evaluates and returns compile time Class object. Looking at the Test.class syntax it looks like the variable class is of type java.lang.Class and is static and public. My question is where is this variable defined? It is not present in Test class (because I don't declare it) neither it is in the java.lang.Object class.
I saw an analogous method public final native Class<?> getClass();. This is present in java.lang.Object and is a native java method. This method returns the runtime Class of an object.
So my question is where is this public & static class variable defined?(Please correct me if I have mistaken) Is it again some native implementation? This is set at compile time and being static needs no class instance to be created. So if even this is some native implementation is it initialized by registerNatives() method in java.lang.Object?
These are called class literals and are defined by the language itself as per JLS §15.8.2 (there is no "class member"):
A class literal is an expression consisting of the name of a class, interface, array, or primitive type, or the pseudo-type void, followed by a '.' and the token class.
The type of C.class, where C is the name of a class, interface, or array type (§4.3), is Class<C>.
The type of p.class, where p is the name of a primitive type (§4.2), is Class<B>, where B is the type of an expression of type p after boxing conversion (§5.1.7).
The type of void.class (§8.4.5) is Class<Void>.
One indication that these constructs are intrinsically built into the language is that they even work with primitives!
System.out.println(int.class);
System.out.println(double.class);
// etc.
class is not normal static variable. It's a language construct which is replaced at compilation time.
Because class is a keyword it wouldn't even be possible to declare a variable with that name.
Your assumption that class is a static field of class Class is not exact. Assume that this is correct. In this case the value of this field will be exactly the same for all classes that is wrong.
Although MyClass.class syntactically looks like access to static field it is just a special syntax of language. Think about this as a kind of operator.
Probably JVM creates some kind of synthetic class that wraps real class and has such field but it is just an assumption about internal representation of classes in JVM.
public class Main {
public static void main(String[] args) {
System.out.println(B.x);
}
}
class A {
public static String x = "x";
}
class B extends A {
static {
System.out.print("Inside B.");
}
}
Question: Why output will be: x. But not: Inside B.x
The reference to B.x issues the following bytecode:
getstatic #3 <Field int B.x>
According to Java Virtual Machine Spec
The Java virtual machine instructions anewarray, checkcast, getfield,
getstatic, instanceof, invokedynamic, invokeinterface, invokespecial,
invokestatic, invokevirtual, ldc, ldc_w, multianewarray, new,
putfield, and putstatic make symbolic references to the runtime
constant pool. Execution of any of these instructions requires
resolution of its symbolic reference.
So the JVM should resolve the symbolic reference to B.x. The field resolution is specified like this:
To resolve an unresolved symbolic reference from D to a field in a
class or interface C, the symbolic reference to C given by the field
reference must first be resolved (§5.4.3.1).
...
When resolving a field reference, field resolution first attempts to
look up the referenced field in C and its superclasses:
If C declares a field with the name and descriptor specified by the
field reference, field lookup succeeds. The declared field is the
result of the field lookup.
Otherwise, field lookup is applied recursively to the direct
superinterfaces of the specified class or interface C.
Otherwise, if C has a superclass S, field lookup is applied
recursively to S.
Otherwise, field lookup fails.
In other words the JVM will resolve B.x into A.x. This is why only A class needs to be loaded.
Because B.x is actually A.x so only the A class needs to be loaded.
§12.4 "Initialization of Classes and Interfaces" of The Java Language Specification, Java SE 7 Edition specifies that:
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class.
[…]
A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.
So although — contrary to claims in some of the answers above — class B does have to be loaded, in order to determine that B.x is declared in A, class B is not initialized (i.e., its static initializers are not actually run) until you do something more specific to B.
It doesn't actually need to load B until it accesses a static member of B directly. Note that this code:
public class TestMain {
public static void main(String[] args) {
System.out.println(B.x);
System.out.println(B.y);
}
static class A {
public static String x = "x";
}
static class B extends A {
public static String y = "y";
static {
System.out.print("Inside B.");
}
}
}
Will output:
x
Inside B.y
Because it doesn't need to load B until something in B is accessed.
Here's a good link on the subject. From the article, "And dont forget, this code will be executed when JVM loads the class. JVM combines all these blocks into one single static block and then executes. Here are a couple of points I like to mention: "
Class B extends A which has an public static variable x which you are accessing when you call B.x
If you expect Inside B. as out put you have to create an Object of that class. All the static code blocks are executed. or move that static code block to class A :-)
When JVM loads class it groups all the static blocks and execute them in the sequence they are declared.
EDIT (Source):
The short answer is that statics are NOT inherited in Java. Rather, the static members declared in a class are (subject to "access" restrictions) directly visible in the namespace of derived classes, unless they "hidden" by declarations in the derived class.
So if the Static belongs to the Class only why does it trickle down to
the derived class ? Shouldn't it just stay with the Class in which it was
defined ?