Archive for May, 2017

Pushing Java Envelope – Part 5: Basic Initializations

03/05/2017

What happens when we run a Java code? Actually, many things occur in a predefined order. Basically, Java tries to run the main() method but before that, an environment must be set. Each runtime has a setup. For Java, certain classes must be loaded. Let’s take a look in an example.

Class Loading

I am using macOS 10.12.4 and Java 1.8.0_92-b14 right now. To get the java version, we can write in command line

java -version

The command java has a parameter to see the classes that are loaded to be run. While getting the version information, we can also learn which classes are being loaded by the JVM to execute that command.

java -verbose:class -version

I did not expect that but the output is really too long to put it here completely. It just starts with this:

init1

ending like this:

init2

If I am not mistaken, there are 352 different class that are loaded to show the version of Java. When I compile and run a very simple class, the number of classes to be loaded for the environment setup increases. It becomes 418 classes. The rt.jar (runtime) file contains all the core Java .class files. The important observation here is that, class loading is interrupted when “something” happens. For example, java version is printed and after that java.lang.Shutdown is loaded. Those “something” is the initializations.

Order of Initializations

We will keep the track of actions over a single code. 

package blog.mertersualp.inits;

public class Initializations { //1
  static { //2
    System.out.println("Class Initalization runs.");
  }
  
  { //3
    System.out.println("Object Initialization Part-1 runs.");
  }
  
  public Initializations() { //4
    System.out.println("Constructor runs.");
  }
  
  public static void main(String[] args) { //5
    System.out.println("main() method runs.");
    Initializations init1 = null;
    System.out.println("What will run next?");
    Initializations init2 = new Initializations();
  }
  
  { //6
    System.out.println("Object Initialization Part-2 runs.");
  }
}

The code above has a few caveats. Each { is the beginning of a code block. So, in here, we have 6 code blocks in total. I have numbered them with comments for reference. Let’s skip the one enclosing the whole class (// 1) and focus on the others. The second code block, //2, is a static one. It is called a Class Initializer, since it will be run in order of appearence, when the class is initialized, not an object of it. The Object Initializers are numbers //3 and //6. When an object of class Initializations is created, these will be run, again, in order of appearance. Hence, we can conclude that “Object Initialization Part-1 runs.” will be printed before “Object Initialization Part-2 runs.” The code block for the constructor of class Initializations is number //4. As the last one, the main() method code is inside block number //5.

Java will first try to find the public static void main(String[] args) method and run it. Java Language Specification states that, anytime a static field or method of a class is accessed, class initializers are run. Since main() is a static method, the very first code block to be run should be //2, which is the static code block. The first line in the console output will be “Class Initialization runs.” So we are inside main() now. It will print “main() method runs.” as the second line. Now here comes the tricky part. An Initializations object, init1 is declared and set to null. Therefore, an object creation/allocation should NOT occur. This means that, “What will run next?” line must be printed before any object specific output.

The init2 object is set by a new object allocation. Since an object is created, the object initialisers and a constructor should be run. The object initialisers always run BEFORE the constructor, since the operations inside a constructor may depend on these object initialisations. Therefore, the last three lines will be “Object Initialization Part-1 runs.”, “Object Initialization Part-2 runs.” and “Constructor runs.”

Here is the final output.

init3

 

Advertisement