I have 2 jars, let's call them a.jar and b.jar.
b.jar depends on a.jar.
In a.jar, I defined a class, let's call it StaticClass. In the StaticClass, I defined a static block, calling a method named "init" :
public class StaticClass {
static {
init();
}
public void static init () {
// do some initialization here
}
}
in b.jar, I have a main, so in the main, I expect that the init() method has been called, but actually not. I suspect that is because the StaticClass has not been loaded by the jvm, could anyone tell me
Is my conclusion correct?
What triggers the jvm to load a class?
How can I get the static block executed automatically?
Thanks
Yes, you are right. Static initialization blocks are run when the JVM (class loader - to be specific) loads StaticClass (which occurs the first time it is referenced in code).
You could force this method to be invoked by explicitly calling StaticClass.init() which is preferable to relying on the JVM.
You could also try using Class.forName(String) to force the JVM to load the class and invoke its static blocks.
Yes you are right, since you are not using your StaticClass it is not loaded by the vm and therefore init() is never executed.
For your second question, you probably have to go the hard way and scan all available classes and load them.
https://stackoverflow.com/a/3223019/393657
First of all class loading is different than class initialization. For anyone looking for explanation from Java Language Specification, when is static block executed - here it is.
The JLS §8.7 says that :
A static initializer declared in a class is executed when the class is initialized (§12.4.2).
So what does the initialization mean? Let's refer to JLS §12.4.2. This describes detailed initialization procedure. However point JLS §12.4.1 might be more appropriate here. It says that :
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 (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
So to make the static initializer block to be executed automatically, you have to force one of those options to happen.
You are right, the easiest way is to access the class, for instance do a
StaticClass.class.newInstance();
Or something to that respect in your main method. This will ensure the class is loaded by the classloader.
The static code is executed when your class (StaticClass I guess) is referenced.
Thus, it should be executed if you create a new instance of StaticClass or if you call one of its static methods.
Static block is executed when a loaded class is initialized or referenced first. Loading class doesnt mean that class is to initialized. JVM Class Loading is separate things to concern.
Yes, the static initializer will be executed when the class is loaded. This normally occurs when you access the class in the class loading context for the first time.
in b.jar main method class should extend that StaticClass then automatically that static block and init() will be invoked
Adding some more:
static block will be executed when jvm load class.
Here in your example you can call init() method of your StaticClass by intantiating class
like
StaticClass staticClass=new StaticClass();
or
StaticClass.class.newInstance(); this is more preferebal
Related
When we say java Test, class loaders will load .class files into method area and static variables if any are initialized to corresponding values assigned and static blocks will be executed.
In java execution means code has to be interpreted by java interpreter. But how static block executes here without interpretation? It is still in a class loading phase, isn’t it?
But in most of the blogs and videos they say once after class loading completes, new thread will be created and it will look for main method and starts executing it. Interpreter comes to picture once main method starts execution in all blogs I saw.
class Test {
static int x = 10;
static {
int y = 10;
System.out.println(x);
}
public static void main(String[] args) {
}
}
The existence of an interpreter is an implementation detail that is irrelevant for describing the behavior of a program. In principle, it is possible to have a JVM without an interpreter at all, as it could have only a compiler that translates all byte code to native code before executing, and still implement the correct behavior. Current desktop and server JVMs have both, executing the code in a mixed mode.
So, it is also irrelevant at which point blogs and videos mention the existence of an interpreter as a way to execute the code, the execution of code always implies the existence of technical means to execute the code, like an interpreter or compiler.
The actual behavior has been specified in The Java Language Specification, §12.4.1:
§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.
¹ this last bullet has been removed from newer specifications
Since the invocation of the main method is an invocation of “a static method declared by” your class, it implies the initialization of that class before the invocation. As you can derive from the last section, if the class containing the main method has uninitialized superclasses, they are initialized even before that class.
For the standard Java launcher, the order of events is
The main thread is created
The main thread loads the specified application class
The super classes of the application class are initialized, if not already initialized
The application class is initialized
The method static void main(String[]) is invoked on the application class
The terms “application class” and “main class” are interchangeable.
Note that this list is only meant to bring these events into the right order. There are far more events happening behind the scenes. Obviously, for asking the application class loader to load the application class, given by name, the classes String, Class, and ClassLoader must have been loaded and initialized, which also implies that their super class, Object has been initialized even before that. The existence of the main thread implies the loading and initialization of the class Thread. And all these classes use other classes behind the scenes.
You may run your application with the -verbose:class option to see which classes are already loaded before your application class.
I have a question regarding static blocks:
Let's say i've got a class looking like this:
class SomeClass {
static {
System.out.println("static block");
}
}
and I define a variable of type SomeClass somewhere.
public static void main(String args[]) {
SomeClass foo;
}
Now i thought the static block would have been executed but it wasn't. As far as i know the static block is executed as soon as the classloader loads the SomeClass class. Now to my real question:
Isn't the class loaded as soon as I define a variable of that type?. If yes why isn't the static block executed?
If the answer should be no, then how can i know if a class has already been loaded by the class loader and what are the different possibilities to have the class loaded (I know of 2: initializing the variable & using a static field/method)
Refer to this doc: http://www.javaworld.com/article/2077260/learn-java/learn-java-the-basics-of-java-class-loaders.html
So when are classes loaded? There are exactly two cases: when the new bytecode is executed (for example, FooClass f = new FooClass();) and when the bytecodes make a static reference to a class (for example, System.out).
In your example, SomeClass foo; does neither execute the bytecode of SomeClass nor make a static reference to SomeClass. That's why the class is not loaded.
So following your example, add a static field in the class
public class SomeClass {
static {
System.out.println("static block");
}
static String abc = "abc";
}
SomeClass is loaded in either:
SomeClass foo = new SomeClass();
Or
System.out.println(SomeClass.abc);
Isn't the class loaded as soon as I define a variable of that type?.
Yes, it is loaded1, but it won't be initialized as a result of declaring a variable. However, when you create an instance of that type, or access a static field of that type, that is sufficient to trigger initialization, including the execution of static blocks.
See this related Q&A - When does static class initialization happen? - which lists all of the things that can trigger initialization.
How can i know if a class has already been loaded by the class loader and what are the different possibilities to have the class loaded (I know of 2: initializing the variable & using a static field/method)
The only ways I can think of for finding out when a class is loaded (as distinct from initialized) are:
turning on the JVM's class loader messages (using -verbose:class), or
using a customer classloader that notices, and does something appropriate when it sees a request to load the class.
A class is actually going to be loaded:
when it is explicitly loaded using Class.forName or similar, or a direct call to a classloader,
when it is necessary to load it in order to link another class, or
at JVM launch time, if the class is named as the entry point class.
The loading / linking / initializing steps are specified in Chapter 12 of the JLS.
1 - In fact, SomeClass needs to be loaded at the same time that the class containing that main method is linked; i.e. before the method containing that local declaration is called.
In the following scenario ,
import A;
public class B{
static A a;
static{
a = new A();
}
}
Is it possible that the static initialization block gets called before a is properly initialized? Note: A here is a logging framework.
In the case you mention above static block will be called before A is initialized as static block will be called when class loads (Class B in your case). So when you do
B.someStaticMethod()
First class B will be loaded where static block is called with it(One time process in JVM) and then static method will be called.
Also Note that Importing statement to load the class does not load the class. It happens when yo do some operation on that class.
Imports have nothing to do with it. There are no imports at runtime.
Referenced classes are loaded during the linking phase, which precedes the initialization phase. In this case A is loaded during the link resolution step for B, before B's static initializer executes.
Reference: JVM Specification: Loading, Linking, and Initializing.
First, it is possible, but not certain, that the static initializer would be called before A is "properly initialized." The static initializer will be executed when B is is loaded by the classloader (see #9: http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2). We don't have enough information from what you've given to know when that will happen relative to A being loaded (the constructor invocation in B's static initializer might be the first time A is loaded, or it might have happened long before).
Second, it's entirely likely that an instance of A being initialized will trigger the initialization of A in a way such that everything will work itself out. Keep in mind that A's constructor won't execute until the class is loaded, which would include running any static initializers for A. So I'm not sure what type of initialization you're worried about that might not happen.
Third, the import statement has nothing to do with any of this. It would behave the same whether you fully qualified com.foo.A used an import statement.
Finally, it would probably be helpful if you provided a real example. If A is just a logging framework, then it's not anything proprietary and you'll probably get a more helpful answer based on what will really happen with that specific framework.
Edit: see the link provided in the comment below for a concrete example.
A class can have any number of static initialization blocks, and they
can appear anywhere in the class body. The runtime system guarantees
that static initialization blocks are called in the order that they
appear in the source code.
Documentation
In order to that it is not possible that the static block gets called before A is properly initialized.
I think there would be no confusion if you initialize your static instance like -
static A a = new A();
static A a;
static{
a = new A();
}
what this code clearly mean is code a = new A(); will be called and initialized only once and remain in permanent generation when class is loaded till main thread exit from the system.
Does this code get called for every object creation in Java, because every object extends Object ? Or does the JVM optimize it in some way to avoid the creation of some many Object's object in the heap.
What exactly happens in this method registerNatives().
package java.lang;
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
Static blocks are only executed once, when the class is loaded.
As explained here or here, a block that will be executed every time an object of the class is initialized can also be defined : just remove the static keyword.
It does n't matter what registerNatives(). does. What does matter here is that you have enclosed it in static block. Static Blocks loaded and run when java Class Loader loads classes. So it is guaranteed to run exactly once per JVM.
1. The question here is not about Constructor chaining, but about static.
2. static variable will be initialized when the JVM loads the class, and JVM loads the class when the class is instantiated or any static method of that class is called.
3. So this static block will run every one time the JVM loads the class.
By default, Sun's JVM both lazily loads classes and lazily initializes (i.e. calls their <clinit> methods) them. Consider the following class, ClinitBomb, which throws an Exception during a static{} block.
public class ClinitBomb {
static {
explode();
}
private static void explode() {
throw new RuntimeException("boom!");
}
}
Now, consider how to trigger the bomb:
public class Main {
public static void main(String[] args) {
System.out.println("A");
try {
Class.forName("ClinitBomb");
} catch (Exception e) {
e.printStackTrace(System.out);
}
System.out.println("B");
ClinitBomb o2 = new ClinitBomb();
System.out.println("C");
}
}
We're guaranteed the explosion happens before point B, since forName's documentation says so; the question is whether it happens before point A (when Main is loaded.) In Sun's JVM, even though main() contains a static reference to ClinitBomb, it happens after A.
I want a way to tell the JVM to load and initialize ClinitBomb as soon as it initializes Main (so the bomb explodes before point A.) In general, I want a way to say, "whenever loading/initializing class X, also do so for any classes Y it references."
Is there a way to do that?
There is no way to do this. The JLS says, in §12.4.1 When Initialization Occurs (emphasis mine):
Initialization of a class consists of executing its static initializers and the initializers for static fields declared in the class. [...]
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 within T is executed.
Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization. A class or interface will not be initialized under any other circumstance.
A Java implementation which initialized classes as soon as they were loaded would violate the JLS.
Although what you could do would be to use the JVM instrumentation API to write a ClassFileTransformer which added a static block to every class which explicitly initialized its referenced classes (via Class.forName, probably). As soon as one class gets initialized, all the classes reachable from it will be initialized. That might give you the result you're after. It's quite a lot of work, though!
Class.forName("...", true /*initialize*/, getClassLoader());
You were halfways there.