Pages

09 April 2012

Final Members and Inlining in Java

Final is a keyword of Java language that can be applied to classes, methods, method variables and class attributes. Briefly, I will list usage and purpose of final keyword with each member.
  1. A class definition with preceding a final keyword indicates that this class cannot be super class of any class. This rule is also applied to member classes, nested classes and local classes.
  2. A final method definition tells the compiler that this method cannot be overriden by any subclass.
  3. A final attribute in a class cannot be reset after its initialization. This attribute is constant in life cycle of any class instance.
  4. A final variable inside a method is constant and cannot be changed after it's set to initial value.
Inspecting these rules makes me think that final keyword is used for disabling inheritance and defining constant values. I also infer that final keyword is absolutely opposite of abstract keyword; so in any case they cannot be used together for a same member.

Inlining Members of Parent Class
Inlining is compile time optimization of java applications that moves the byte code of final and in some situations non-final members to subclass. Generally, the motivation of inlining is duplicating a unique attribute or method code of parent class to subclass. As a result instead of dynamic dispatch, from all subclasses to parent's code; moving the code to subclasses in compile time will reduce execution speed and increase the performance of application.

Final methods and final accessible variables from sublcasses are best candidates because it is guaranteed that they cannot be overriden by subclasses. Thus many people think that only way to succeed inlining is defining final members. However, methods that are not overriden by subclasses can also be good candidates after subclasses' source is evaluated at compile time.

I used JDK 1.6.0.30 version to evaluate this feature; but i could only observe inlining parent class' accessible final attribute. Other JVM' s compilation might show different results.

First, all classes are compiled and main method in Test class is run. Then, all final and non-final methods and attributes in Parent class are changed. When Test class is run again, the output indicates that only accessible final attribute of Parent class is inlined to Subclass.

Test.java
public class Test {

 public static void main(String[] args) {
  Child c = new Child();
  // not overriden non-final method inlining
  System.out.println(c.getName());
  // accessible final attribute inlining
  System.out.println(c.name);
  // accssible non-final attribute inlining
  System.out.println(c.id);
  // final method inlining that returns String
  System.out.println(c.m1());
  // final method inlining that returns primitive int
  System.out.println(c.m2());  
 }
}
Child.java
public class Child extends Parent { }
Parent.java
public class Parent {

 public final String name = "Parent.name";
 public String id = "Parent.id";
 
 public final String m1() {
  return "Parent.m1()";
 }
 
 public final int m2() {
  return 5;
 }

 public String getName() {
  return "Parent.getName()";
 }
}

1. Compile and run Test class as follows.

H:\Inlining>javac *.java

H:\Inlining>java Test
Parent.getName()
Parent.name
Parent.id
Parent.m1()
5

2. Change the source of Parent class then compile only this class. Then run Test class again. Only Parent.name is same with first output, this result shows us only accessible parent final attribute is inlined.

public class Parent {

 public final String name = "Parent.name v2";
 public String id = "Parent.id v2";
 
 public final String m1() {
  return "Parent.m1() v2";
 }
 
 public final int m2() {
  return 52;
 }

 public String getName() {
  return "Parent.getName() v2";
 }
}


H:\Inlining>javac Parent.java

H:\Inlining>java Test
Parent.getName() v2
Parent.name
Parent.id v2
Parent.m1() v2
52

H:\Inlining>java -version
java version "1.6.0_30"
Java(TM) SE Runtime Environment (build 1.6.0_30-b12)
Java HotSpot(TM) Client VM (build 20.5-b03, mixed mode, sharing)

Take care...

Edit: Same result on AIX

user:host:/home/guest:>java -version
java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2)
Classic VM (build 1.4.2, J2RE 1.4.2 IBM AIX ... (JIT enabled: jitc))