What does "When a Class is loaded" actually mean? - java

It is said that static blocks in java run only once when that class is loaded. But what does it actually mean? At which point is a class loaded by JVM (Java Virtual Machine)?
Is it when the main method in that class is called? And is it that all the super-classes of the same class are also loaded when the main method starts execution?
Consider that A extends B and B extends C. All have static blocks. If A has the main method, then what will be the sequence of execution of static blocks?

This is described in the Execution section of the JLS. Namely:
Initialization of a class consists of executing its static initializers and the initializers for static fields declared in the class. Initialization of an interface consists of executing the initializers for fields declared in the interface.
Before a class is initialized, its direct superclass must be initialized, but interfaces implemented by the class need not be initialized. Similarly, the superinterfaces of an interface need not be initialized before the interface is initialized.
So in your example, the static block of the "topmost" class (C) runs first, then that of B, then the most-derived one.
See that documentation for a detailed description of all the steps that go into loading a class.
(Classes get loaded when they are first actively used.)

I think the following example will solve all of your problems:
Before a class is initialized, its superclasses are initialized, if they have not previously been initialized.
Thus, the test program:
class Super {
static { System.out.print("Super "); }
}
class One {
static { System.out.print("One "); }
}
class Two extends Super {
static { System.out.print("Two "); }
}
class Test {
public static void main(String[] args) {
One o = null;
Two t = new Two();
System.out.println((Object)o == (Object)t);
}
}
prints:
Super Two false
The class One is never initialized, because it not used actively and therefore is never linked to. The class Two is initialized only after its superclass Super has been initialized.
For more details visit this link
Edit details: Removed confusing lines.

From the Java Language Specification:
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class. Initialization of an interface consists of executing the initializers for fields (constants) declared there.
Before a class is initialized, its superclass must be initialized, but interfaces implemented by the class are not initialized. Similarly, the superinterfaces of an interface are not initialized before the interface is initialized.
The process is described in more detail in the Java Virtual Machine Specification.

Related

Is the class loaded when its reference is declared?

Does creating a reference to an object of a class cause the class to be loaded?
Static variables are initialized when the class is loaded, so considering the following code the answer is no, am I right?
class A{
static int f(){
System.out.println("initializing!");
return 0;
}
static final int i = f();
}
public class Main {
public static void main(String[] args) {
A a;
}
}
The code doesn't give any output.
It’s a common mistake to treat loading and initialization of a class as being the same thing.
The Java Language Specification differentiates between
Loading
Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a Java compiler, and constructing, from that binary form, a Class object to represent the class or interface.
Linking
Linking is the process of taking a binary form of a class or interface type and combining it into the run-time state of the Java Virtual Machine, so that it can be executed. A class or interface type is always loaded before it is linked.
Three different activities are involved in linking: verification, preparation, and resolution of symbolic references.
Initialization
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class.
Initialization of an interface consists of executing the initializers for fields (constants) declared in the interface.
For most cases, the exact time of loading and linking doesn’t matter, so it’s no problem that the specification provides some freedom to JVM implementations regarding the exact time. Only in the erroneous case, e.g. when a class is absent or there are incompatibilities (linkage or verify errors), JVM specific differences can show up, regarding the exact time when the associated Error is thrown.
So what your question is aiming at, is not loading, but initialization as you are looking at the side effect produced by the execution of the static class intializer.
The time of initialization is precisely defined:
§12.4.1. When Initialization Occurs
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.
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 field is not a constant variable (§4.12.4).
T is a top level class (§7.6) and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
When a class is initialized, its superclasses are initialized (if they have not been previously initialized), as well as any superinterfaces (§8.1.5) that declare any default methods (§9.4.3) (if they have not been previously initialized). Initialization of an interface does not, of itself, cause initialization of any of its superinterfaces.
So from the specification, you can draw the conclusion that the mere presence of a local variable will never trigger an initialization. When assigning a non-null value to a variable of a reference type, there must have been a preceding instantiation of that type that already triggered its initialization. An unused local variable, however, has no impact.
When it comes to loading rather than initialization, there can be subtle differences, as shown is this scenario.
Yes. Static initializers are called when a class method is called or an instance is instantiated.
From your example you can do one of the following:
1. Create New Instance
public static void main(String[] args) {
A a = new A();
}
2. Call Static Class Method
public static void main(String[] args) {
int f = A.f();
}

static and instance method in java -Parent and Sub class

Why cant we declare an instance method in sub Class B which shares the same signature of a static method in parent Class A?
It throws a compile time error if i try to do that.
My question is, since static method of parent class is restricted to parent class, why does instance method of child class does not compile.
Lets see by code:
`
public class A{
static void testStatic(){}
}
public class B extends A{
void testStatic (){}
}
public class Test{
public static void main (String[] args){
A a = new B()
a.testStatic();
}
`
In the above code,since A does not have an instance method by that name, and since Java allows static methods to be accessed by objects, Object a of type 'A' pointing to 'B' can call static method present in it(class A). But complier throws an error "The instance method cannot override a static method" why?
Note: I can understand if a class does not allow same method name for two methods, even if one is instance and other is static. But I fail to understand why it does not allow a sub class to have an instance of same name. Especially considering the fact that static methods cannot be overridden. And yet, Java allows subclass to have same name as parent class static method, which is called information hiding, but not overriding.
The compiler throws an error because those are the rules of the language. From the Java Language Specification §8.4.8.2:
If a class C declares or inherits a static method m, then m is said to hide any method m', where the signature of m is a subsignature (§8.4.2) of the signature of m', in the superclasses and superinterfaces of C that would otherwise be accessible to code in C.
It is a compile-time error if a static method hides an instance method.
(emphasis in the original). The language is dense (as in most places in the JLS) but it matches the situation you are describing. The JLS doesn't provide a rationale for this rule that I could find on first reading. But a little thought about how one might try to make this rule unnecessary shows why it's there.
It's illegal in Java. The call to the static method is allowed on an instance as well, so there'd be no way to distinguish which method to call in some cases:
A a = new A ();
B b = new B ();
A.testStatic (); // ok
B.testStatic (); // ok
a.testStatic (); // ok calling static
b.testStatic (); // undefined. What to call? Based on what?
Last call is the reason why it's not allowed.
Calls to static methods are resolved at compile time itself. So, they cannot be overridden. And by defining another method with the same signature as the static method, the compiler complains.
static method is bound with class whereas instance method is bound with object.
Static belongs to class area and instance belongs to heap area.
I am not hundred percent sure but I guess answer as below.
Static method means it can be used without an instance of the the class in which it is defined. Also static method can access only static variables of the class. Now if we override non static method and create an instance of sub class with reference of the super class, compiler will be confused for above two basic functioning of static method. Please debate if any thing wrong in this.
4 line showing error. so do this
public class B extends A

Why is a subclass' static initializer not invoked when a static method declared in its superclass is invoked on the subclass?

Given the following classes:
public abstract class Super {
protected static Object staticVar;
protected static void staticMethod() {
System.out.println( staticVar );
}
}
public class Sub extends Super {
static {
staticVar = new Object();
}
// Declaring a method with the same signature here,
// thus hiding Super.staticMethod(), avoids staticVar being null
/*
public static void staticMethod() {
Super.staticMethod();
}
*/
}
public class UserClass {
public static void main( String[] args ) {
new UserClass().method();
}
void method() {
Sub.staticMethod(); // prints "null"
}
}
I'm not targeting at answers like "Because it's specified like this in the JLS.". I know it is, since JLS, 12.4.1 When Initialization Occurs reads just:
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 a static method declared by T is invoked.
...
I'm interested in whether there is a good reason why there is not a sentence like:
T is a subclass of S and a static method declared by S is invoked on T.
Be careful in your title, static fields and methods are NOT inherited. This means that when you comment staticMethod() in Sub , Sub.staticMethod() actually calls Super.staticMethod() then Sub static initializer is not executed.
However, the question is more interesting than I thought at the first sight : in my point of view, this shouldn't compile without a warning, just like when one calls a static method on an instance of the class.
EDIT: As #GeroldBroser pointed it, the first statement of this answer is wrong. Static methods are inherited as well but never overriden, simply hidden. I'm leaving the answer as is for history.
I think it has to do with this part of the jvm spec:
Each frame (§2.6) contains a reference to the run-time constant pool (§2.5.5) for the type of the current method to support dynamic linking of the method code. The class file code for a method refers to methods to be invoked and variables to be accessed via symbolic references. Dynamic linking translates these symbolic method references into concrete method references, loading classes as necessary to resolve as-yet-undefined symbols, and translates variable accesses into appropriate offsets in storage structures associated with the run-time location of these variables.
This late binding of the methods and variables makes changes in other classes that a method uses less likely to break this code.
In chapter 5 in the jvm spec they also mention:
A class or interface C may be initialized, among other things, as a result of:
The execution of any one of the Java Virtual Machine instructions new, getstatic, putstatic, or invokestatic that references C (§new, §getstatic, §putstatic, §invokestatic). These instructions reference a class or interface directly or indirectly through either a field reference or a method reference.
...
Upon execution of a getstatic, putstatic, or invokestatic instruction, the class or interface that declared the resolved field or method is initialized if it has not been initialized already.
It seems to me the first bit of documentation states that any symbolic reference is simply resolved and invoked without regard as to where it came from. This documentation about method resolution has the following to say about that:
[M]ethod resolution attempts to locate the referenced method in C and its superclasses:
If C declares exactly one method with the name specified by the method reference, and the declaration is a signature polymorphic method (§2.9), then method lookup succeeds. All the class names mentioned in the descriptor are resolved (§5.4.3.1).
The resolved method is the signature polymorphic method declaration. It is not necessary for C to declare a method with the descriptor specified by the method reference.
Otherwise, if C declares a method with the name and descriptor specified by the method reference, method lookup succeeds.
Otherwise, if C has a superclass, step 2 of method resolution is recursively invoked on the direct superclass of C.
So the fact that it's called from a subclass seems to simply be ignored. Why do it this way? In the documentation you provided they say:
The intent is that a class or interface type has a set of initializers that put it in a consistent state, and that this state is the first state that is observed by other classes.
In your example, you alter the state of Super when Sub is statically initialized. If initialization happened when you called Sub.staticMethod you would get different behavior for what the jvm considers the same method. This might be the inconsistency they were talking about avoiding.
Also, here's some of the decompiled class file code that executes staticMethod, showing use of invokestatic:
Constant pool:
...
#2 = Methodref #18.#19 // Sub.staticMethod:()V
...
Code:
stack=0, locals=1, args_size=1
0: invokestatic #2 // Method Sub.staticMethod:()V
3: return
The JLS is specifically allowing the JVM to avoid loading the Sub class, it's in the section quoted in the question:
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.
The reason is to avoid having the JVM load classes unnecessarily. Initializing static variables is not an issue because they are not getting referenced anyway.
The reason is quite simple: for JVM not to do extra work prematurely (Java is lazy in its nature).
Whether you write Super.staticMethod() or Sub.staticMethod(), the same implementation is called. And this parent's implementation typically does not depend on subclasses. Static methods of Super are not supposed to access members of Sub, so what's the point in initializing Sub then?
Your example seems to be artificial and not well-designed.
Making subclass rewrite static fields of superclass does not sound like a good idea. In this case an outcome of Super's methods will depend on which class is touched first. This also makes hard to have multiple children of Super with their own behavior. To cut it short, static members are not for polymorphism - that's what OOP principles say.
According to this article, when you call static method or use static filed of a class, only that class will be initialized.
Here is the example screen shot.
for some reason jvm think that static block is no good, and its not executed
I believe, it is because you are not using any methods for subclass, so jvm sees no reason to "init" the class itself, the method call is statically bound to parent at compile time - there is late binding for static methods
http://ideone.com/pUyVj4
static {
System.out.println("init");
staticVar = new Object();
}
Add some other method, and call it before the sub
Sub.someOtherMethod();
new UsersClass().method();
or do explicit Class.forName("Sub");
Class.forName("Sub");
new UsersClass().method();
When static block is executed Static Initializers
A static initializer declared in a class is executed when the class is initialized
when you call Sub.staticMethod(); that means class in not initialized.Your are just refernce
When a class is initialized
When a Class is initialized in Java After class loading, initialization of class takes place which means initializing all static members of class. A Class is initialized in Java when :
1) an Instance of class is created using either new() keyword or using reflection using class.forName(), which may throw ClassNotFoundException in Java.
2) an static method of Class is invoked.
3) an static field of Class is assigned.
4) an static field of class is used which is not a constant variable.
5) if Class is a top level class and an assert statement lexically nested within class is executed.
When a class is loaded and initialized in JVM - Java
that's why your getting null(default value of instance variable).
public class Sub extends Super {
static {
staticVar = new Object();
}
public static void staticMethod() {
Super.staticMethod();
}
}
in this case class is initialize and you get hashcode of new object().If you do not override staticMethod() means your referring super class method
and Sub class is not initialized.

Concepts in Inheriting a Static method

I have 2 classes as below
public class statictest {
public void print()
{
System.out.println("first one");
}
}
public class newer extends statictest
{
public void print()
{
System.out.println("second one");
}
}
and in the main function I do
statictest temp = new newer();
newer temp2 = new newer();
temp.print();
temp2.print();
Output is :
second one
second one
But When I make these 2 methods static the output is
firstone
secondone
what happened to late binding in this case?? Can anyone explain
This is called dynamic method invocation. You can look on this JLS.
It states,
The strategy for method lookup depends on the invocation mode.
If the invocation mode is static, no target reference is needed and
overriding is not allowed. Method m of class T is the one to be
invoked.
Otherwise, an instance method is to be invoked and there is a target
reference. If the target reference is null, a NullPointerException is
thrown at this point. Otherwise, the target reference is said to refer
to a target object and will be used as the value of the keyword this
in the invoked method. The other four possibilities for the invocation
mode are then considered.
static methods can not be overridden, they remains hidden if redefined in subclasses.
Ps: they do take part in inheritance. you can access static methods, from subclass name.
It is because static methods are not polymorphic. Static methods will not be Overridden.
Do search on Dynamic method dispatch
Static methods can't be overridden, that is why after making it static you are getting output like this.
static methods can not overridden.
you created object for newer class by using statictest class reference variable temp2 u hold that object by using super class reference variable. At the time of compilation compiler just checks syntax weather that method is available in the statictest class or not.if it is available it complies fine otherwise error will come.your code you declared static print method so it is availble in statictest class compilation done fine but your method is static it can't be override. now coming main method u declared
statictest temp = new newer();
now temp object is created with statictest class features only. it won't contains newer class methods or variables object is created based on the referenced class properties only it won't contains subclass properties(newer class) if super class(statictest) contains any non static values same as sub class(newer class) just it will overrides super class properties. why it overrides? because with the class it will not allow to declare same varibles or same methods

Is static code always executed when we use a class for the first time?

Our application is using initialization code that depends on the order static code is executed and I'm wondering if this order will be consistent across all JVMs.
Here is a sample of what I mean:
public class Main {
static String staticVar = "init_value";
public static void main(String[] args) {
System.out.println(A.staticVar);
staticVar = "mainValue";
System.out.println(A.staticVar);
}
}
public class A {
static String staticVar = Main.staticVar;
}
will give:
init_value
init_value
and
public class Main {
static String staticVar = "init_value";
public static void main(String[] args) {
// System.out.println(A.staticVar);
staticVar = "mainValue";
System.out.println(A.staticVar);
}
}
public class A {
static String staticVar = Main.staticVar;
}
will give (on my environment):
mainValue
To summarize, across all JVMs, is static code always executed when we use a class for the first time?
EDIT: Despite all the reassurances below, if you're thinking of relying on this sort of thing, I would try hard to refactor your code so that it doesn't crop up. While it is guaranteed to work, it's also likely to make your code very brittle. The fact that static initializers get called "invisibly" makes them relatively hard to reason about and debug.
Yes, this is guaranteed by the language specification. From section 8.7 of the spec:
Any static initializers declared in a class are executed when the class is initialized and, together with any field initializers (§8.3.2) for class variables, may be used to initialize the class variables of the class (§12.4).
StaticInitializer: static Block
It is a compile-time error for a static initializer to be able to complete abruptly (§14.1, §15.6) with a checked exception (§11.2). It is a compile-time error if a static initializer cannot complete normally (§14.21).
The static initializers and class variable initializers are executed in textual order.
And from section 12.4:
Initialization of a class consists of
executing its static initializers and
the initializers for static fields
declared in the class. Initialization
of an interface consists of executing
the initializers for fields declared
in the interface.
Before a class is
initialized, its direct superclass
must be initialized, but interfaces
implemented by the class need not be
initialized. Similarly, the
superinterfaces of an interface need
not be initialized before the
interface is initialized.
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 field is not a
constant variable (§4.12.4).
T is a
top-level class, and an assert
statement (§14.10) lexically nested
Static initialisers (e.g. your staticVar declarations) are always executed when you use a class for the first time.
Static methods are only executed when they are called. In your case, this is happening because the static void main(String[] args) is the entry point to your application. But if you defined a different static method then it would not be called.
It is also possible to create a static initialiser block that will also be called automatically before the class is first used, e.g.
static {
// some initialisation code here
}
That should be all the same on all platforms. See JVM Specification : http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#19075
A quote from Java specification:
Initialization of a class consists of
executing its static initializers and
the initializers for static fields
declared in the class. Initialization
of an interface consists of executing
the initializers for fields declared
in the interface.
Yes, according to the Java Language Specification static code is always executed in the same order on all (compliant) JVM's.
8.7 Static Initializers
The static initializers and class variable initializers are executed in textual order.
Dittos to other posters, but let me add that a static initializer that depends on the state of other classes like in your example seems to me to make for very fragile and difficult-to-maintain code. I'll use static intializers to populate internal class data -- to fill up an array with default values or that sort of thing. But I don't think I've ever had one peek at the data in another class. Technically legal, and maybe there are odd cases where it's a good idea, but yuck.
Yes, I believe that would be the point by definition.
Static Block will always run first not just the first time... Before executing any code block, JVM execute the static code block first, and then only it run the code block as it has been designed...

Categories