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.
Related
We cant access non static instance from a static method. But main() method is static and runs first. During initialization of any other class in main method, it will call the constructor. Is that constructor static ? what is the basic flow for JVM ?
The main method is called by the JVM to run the method which is outside the scope of project.
When the JVM calls the main method, there is no object existing for the class being called. So it has to have static method to allow this from class.
During initialization of any other class in main method, it will call the constructor.
If you mean instantiation, then Yes it will. Creating an instance of a class calls the constructor, whether the new call is made in main or anywhere else.
If you really do mean class initialization (which typically happens implicitly), then No it won't. The initialization of a class does no involve the classes constructors.
For example
public class Example {
private static int foo = OtherClass.someMethod();
static {
// do something
}
public Example() {
// do something
}
}
Class initialization executes the initializer for foo and the static initializer block, but is doesn't execute the constructor. Creating an instance of Example calls the Example() constructor.
Is that constructor static ?
Constructors are always static ... in the sense that new doesn't require an existing instance.
Yes, we can't access non-static variables from static block because, non-static variable are instance variables & can only be accessed by creating an object of class with new operator or using reflection like Class.newInstance(). Whereas, static variables are class level & it's value is constant for every single object. It means no need to create an object of a class to access those variables. You can access static variable by using class name (different class) or directly (within same class) like :-
public class HelloWorld {
private static String message = "Hello";
public static void main(String[] args) {
System.out.println(message);
System.out.println(HelloWorld1.sayHello);
}
}
public class HelloWorld1 {
public static String sayHello = "Hello1";
}
main() method :
public static void main(String[] args) {}
In Java, main() method is static & it's the entry point of JVM. Since, main() method doesn't belong to any class in Java. When we define main() method in any user-defined class, then it will belong to that class. And since it's static & within the same class, no need to access it using class name. The main method is directly available to JVM.
How JVM works :
When there is need to execute to any Java class ClassLoader comes into picture. The Java Classloader is a part of the Java Runtime Environment that dynamically loads Java classes into the Java Virtual Machine.
Image taken from : Understanding JVM Internals
When JVM starts to execute a Java file, it'll
First compile .java file & convert it into .class file which contains bytecode i.e, machine language or assembly language. Each time the same bytecodes are processed, JVM works with JIT (Just-In-Time) compiler to convert byte code into native code.
Loads the .java file & necessary packages using System Class Loader & BoostrapperClassLoader resp.
After loading, JVM will look into .class file & store all information like variables, packages, methods, etc & save them into a memory & initialize all the field variables.
The JVM then starts interpreting bytecode & displays the result of that in human readable form.
Say I have a static method increment:
public class StaticTest {
private static int no = 0;
public static void increment()
{
no++;
}
}
When I call increment using the StaticTest.increment() syntax, does the class ever get instantiated? What if no object of that type exists on the heap already?
When I call increment using the StaticTest.increment() syntax, does the class ever get instantiated?
The class, itself, is loaded (by the classloader), if it isn't already loaded. If it's already loaded, it is not loaded a second time. No instances of the class (objects of that class's type) are created, because you haven't created any.
Assuming all of the code that calls StaticTest.increment() is using the same classloader (which is normally the case), it doesn't matter how many different bits of code call that static method, just a single copy of the class is used. They all share it. E.g.:
// Some bit of code somewhere
StaticTest.increment();
// Another bit of code somewhere else
StaticTest.increment();
// A third bit of code in yet another place
StaticTest.increment();
Once all of those have run, the no private static member in StaticTest has the value 3.
What if no class of that type exists on the heap already?
Then then classloader loads it.
Contrast that code with this (no statics):
public class NonStaticTest {
private int no = 0;
public void increment()
{
no++;
}
public int getNo() // So we can see the results
{
return no;
}
}
Now, we can't do this:
NonStaticTest.increment(); // WRONG, fails with error saying `increment` is not static
We do this instead:
NonStaticTest instance = new NonStaticTest();
instance.increment();
System.out.println(instance.getNo()); // "1"
The first time code does that, the NonStaticTest class is loaded by the classloader. Then, the new NonStaticTest() expression creates an instance of the class, which has a no member. The second time code does that, NonStaticTest has already been loaded, so it's not loaded again. Then the new NonStaticTest() expression creates a second instance of the class.
If we had three bits of code all doing the above, each of them would see "1", because no is specific to an instance of the class rather than being attached to the class itself.
You have to clearly differentiate between 2 things:
classes, which are sort of "custom types" (I'm simplifying here)
objects, which are instances of these classes
Classes are loaded once by the classloader, whereas objects of a class are created each time you call new ClassName() (if the class is called ClassName).
Now, back to your problem: the use of the static keyword makes your declarations independant of any instance (object) of your class.
Therefore, when you use StaticTest.increment(), no object of the class StaticTest is created (and no object is needed).
You instantiate an instance with new StaticTest and unless you created one of those, you haven't created an instance.
Conside this code:
class MyClass {
private static MyClass myobj = new MyClass();
private MyClass() {
}
public static MyClass getMyobj() {
return myobj;
}
}
1)IN above code when will myobj get initialiazed-when Myclass gets loaded OR when getMyobj() will be called first time as MyClass.getMyobj();?
2) Suppose we call twice as:
MyClass.getMyobj();
MyClass.getMyobj();
will it create new MyClass() object on second call?
When your class will be loaded
No , it won't create another object, it will use the already existing one
1)IN above code when will myobj get initialiazed
When the class is first loaded.
2) Suppose we call twice as:...will it create new MyClass() object on second call?
No mainly because myobj is static so getMyobj() will always return the same instance, the one created at load time.
When MyClass gets loaded.
Even if you call it ten times, only one instance exists for MyClass.
As has been pointed out the object will be created when the class is initialised, and because the method simply returns it, no other such instances will be created in the example code.
However, if you want to do such a thing you could also create an enum with a single instance:
public enum MyClass {
myobj;
}
Then code which needs to work with myobj can simply access the MyClass.myobj field while the code itself retains singleton behaviour. Of course a similar effect may be accomplished with a public static final field.
The enum has the benefit that the compiler knows you do not want to accidentally create arbitrary objects. It has the downside that if you want lazy initialisation instead you would need to introduce an additional delegate for the lazily loaded part.
As soon as MyClass is loaded, it will get initialized.But it will initialize only one time.
It is not correct to say that a class gets initialised as soon as it is loaded. A class will only be initialised once a running program creates an instance of that class (by calling its constructor with the new keyword) or once any of the static methods or fields belonging to the class are used.
See the Java Language Specification section 12.4.1 for the JVM rules on initialisation.
I should point out that I only know this thanks to the excellent book by Joshua Bloch, "Effective Java, Second Edition". Item 71 offers advice about lazy initialization and the "lazy initialization holder class idiom".
So, in answer to your question, MyClass.myobj will only be initialised when a running program (such as your main() method) actually makes a call to MyClass.getMyobj() and not a moment before then.
And because static fields are only initialised once per class, the next time MyClass.getMyobj() is called, it will simply return the existing value for MyClass.myobj, so you will get two references to exactly the same MyClass object.
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
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.