I was reading a recent blog entry from A. Sundararajan which uncovers one of the hidden options used to be available only for debugging Java compiler. This option is an undocumented feature which explains the underpinnings behind some of the various language features introduced in JDK1.5. OpenJDK provides an opportunity to learn the intricacies of Java compiler implementation. Sundararajan’s blog uncovers the implementation of inner classes in Java. I am going to use the samples which I used in my JDK1.5 article on developer.com. The bottom line is you would see how the new language features are implemented using the plain old java syntax (POJS) and sometimes these are verbose and ugly (See how Enums are compiled). This a good example of abstraction where the complexity is hidden by the compiler. The transformations are fairly straightforward. I will leave up to the reader to dig into this.
Here is how you use the hidden option -XD to printflat when compiling a Java program.
javac -d tmp -XD-printflat EnumFacility.java
This will create the files in tmp directory. Make sure you don’t try compiling a file from the same directory. It would fail to overwrite the input file.
Generic Class
public class C { private T1 type1; private T2 type2; public C(T1 type1, T2 type2) { this.type1 = type1; this.type2 = type2; } public T1 getType1() { return this.type1; } public T2 getType2() { return this.type2; } public static void main(String args[]) { C cStrInt = new C("one", 1); String type1StrInt = cStrInt.getType1(); Integer type2SI = cStrInt.getType2(); C cIntBool = new C(1, true); Integer type1IntStr = cIntBool.getType1(); Boolean type2IntStr = cIntBool.getType2(); } }
Generic Class (with printflat)
public class C { private Object type1; private Object type2; public C(Object type1, Object type2) { super(); this.type1 = type1; this.type2 = type2; } public Object getType1() { return this.type1; } public Object getType2() { return this.type2; } public static void main(String[] args) { C cStrInt = new C("one", Integer.valueOf(1)); String type1StrInt = (String)cStrInt.getType1(); Integer type2SI = (Integer)cStrInt.getType2(); C cIntBool = new C(Integer.valueOf(1), Boolean.valueOf(true)); Integer type1IntStr = (Integer)cIntBool.getType1(); Boolean type2IntStr = (Boolean)cIntBool.getType2(); } }
Generic Interface
public interface I { public T getConnectionPool(); public void releaseConnectionPool(T connectionPool); }
Generic Interface (with printflat)
public interface I { public Object getConnectionPool(); public void releaseConnectionPool(Object connectionPool); }
Generic Method
public class M { public static <T extends Comparable> T minimum(T a, T b) { if(a.compareTo(b) <= 0) return a; else return b; } public static void main(String[] args) { Integer b1 = new Integer(2); Integer b2 = new Integer(5); Integer min = minimum(b1, b2); System.out.println("Minimum of (2,5) : " + min); } }
Generic Method (with printflat)
public class M { public M() { super(); } public static Comparable minimum(Comparable a, Comparable b) { if (a.compareTo(b) <= 0) return a; else return b; } public static void main(String[] args) { Integer b1 = new Integer(2); Integer b2 = new Integer(5); Integer min = (Integer)minimum(b1, b2); System.out.println("Minimum of (2,5) : " + min); } }
Generic Collections
public class CollectionFiltering { static void purgeFromCollection(Collection c) { for (Iterator i = c.iterator(); i.hasNext(); ) { if(i.next().length() == 4) i.remove(); } System.out.println(c); } public static void main(String args[]) { List arrayList = new ArrayList(); arrayList.add(new String("One")); arrayList.add(new String("Two")); arrayList.add(new String("Three")); arrayList.add(new String("Four")); System.out.println(arrayList); purgeFromCollection(arrayList); } }
Generic Collections (with printflat)
public class CollectionFiltering { public CollectionFiltering() { super(); } static void purgeFromCollection(Collection c) { for (Iterator i = c.iterator(); i.hasNext(); ) { if (((String)i.next()).length() == 4) i.remove(); } System.out.println(c); } public static void main(String[] args) { List arrayList = new ArrayList(); arrayList.add(new String("One")); arrayList.add(new String("Two")); arrayList.add(new String("Three")); arrayList.add(new String("Four")); System.out.println(arrayList); purgeFromCollection(arrayList); } }
Enums
public class EnumFacility { enum Continent { africa , asia, europe, north_america, oceania, south_america }; public static void main(String args[]) { for ( Continent c : Continent.values() ) { // switch on enum switch(c) { case africa: System.out.println("in africa."); break; case asia: System.out.println("in asia."); break; case europe: System.out.println("in europe."); break; case north_america: System.out.println("in north_america."); break; case oceania: System.out.println("in oceania."); break; case south_america: System.out.println("in south_america."); break; } } } }
Enums (with printflat)
public class EnumFacility { { } public EnumFacility() { super(); } { } { } public static void main(String[] args) { for (EnumFacility$Continent[] arr$ = EnumFacility$Continent.values(), len$ = arr$.length, i$ = 0; i$ < len$; ++i$) { EnumFacility$Continent c = arr$[i$]; { switch (EnumFacility$1.$SwitchMap$EnumFacility$Continent[c.ordinal()]) { case 1: System.out.println("in africa."); break; case 2: System.out.println("in asia."); break; case 3: System.out.println("in europe."); break; case 4: System.out.println("in north_america."); break; case 5: System.out.println("in oceania."); break; case 6: System.out.println("in south_america."); break; } } } } }
/*synthetic*/ class EnumFacility$1 { /*synthetic*/ static final int[] $SwitchMap$EnumFacility$Continent = new int[EnumFacility.Continent.values().length]; static { try { EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.africa.ordinal()] = 1; } catch (NoSuchFieldError ex) { } try { EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.asia.ordinal()] = 2; } catch (NoSuchFieldError ex) { } try { EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.europe.ordinal()] = 3; } catch (NoSuchFieldError ex) { } try { EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.north_america.ordinal()] = 4; } catch (NoSuchFieldError ex) { } try { EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.oceania.ordinal()] = 5; } catch (NoSuchFieldError ex) { } try { EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.south_america.ordinal()] = 6; } catch (NoSuchFieldError ex) { } } }
enum EnumFacility$Continent extends Enum { /*public static final*/ africa /* = new EnumFacility$Continent("africa", 0) */, /*public static final*/ asia /* = new EnumFacility$Continent("asia", 1) */, /*public static final*/ europe /* = new EnumFacility$Continent("europe", 2) */, /*public static final*/ north_america /* = new EnumFacility$Continent("north_america", 3) */, /*public static final*/ oceania /* = new EnumFacility$Continent("oceania", 4) */, /*public static final*/ south_america /* = new EnumFacility$Continent("south_america", 5) */; /*synthetic*/ private static final EnumFacility$Continent[] $VALUES = new EnumFacility$Continent[] {EnumFacility$Continent.africa, EnumFacility$Continent.asia, EnumFacility$Continent.europe, EnumFacility$Continent.north_america, EnumFacility$Continent.oceania, EnumFacility$Continent.south_america}; public static EnumFacility$Continent[] values() { return (EnumFacility$Continent[])$VALUES.clone(); } public static EnumFacility$Continent valueOf(String name) { return (EnumFacility$Continent)Enum.valueOf(EnumFacility.Continent.class, name); } private EnumFacility$Continent(/*synthetic*/ String $enum$name, /*synthetic*/ int $enum$ordinal) { super($enum$name, $enum$ordinal); } }
AutoBoxing
public class AutoBoxing { static List testAutoBoxing(int ii) { int i = 0; List arrayList = new ArrayList(); arrayList.add(++i); arrayList.add(new Integer(11)); arrayList.add(++ii); return arrayList; } public static void main(String args[]) { List arrayList = testAutoBoxing(110); for (Integer i : arrayList) System.out.println(i); } }
AutoBoxing (with printflat)
public class AutoBoxing { public AutoBoxing() { super(); } static List testAutoBoxing(int ii) { int i = 0; List arrayList = new ArrayList(); arrayList.add(Integer.valueOf(++i)); arrayList.add(new Integer(11)); arrayList.add(Integer.valueOf(++ii)); return arrayList; } public static void main(String[] args) { List arrayList = testAutoBoxing(110); for (Iterator i$ = arrayList.iterator(); i$.hasNext(); ) { Integer i = (Integer)i$.next(); System.out.println(i); } } }
Enhanced For Statement
public class EnhancedForLoop { public void testEnhancedForLoop() { int [] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int sum = 0; for (int e : a) sum += e; System.out.println("Array Sum : " + sum); } }
Enhanced For Statement (with printflat)
public class EnhancedForLoop { public EnhancedForLoop() { super(); } public void testEnhancedForLoop() { int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int sum = 0; for (int[] arr$ = a, len$ = arr$.length, i$ = 0; i$ < len$; ++i$) { int e = arr$[i$]; sum += e; } System.out.println("Array Sum : " + sum); } }
Annotations
public class Annotations extends java.lang.Object { @SuppressWarnings("deprecation") public static void suppressWarnings() { //implementation } @Deprecated public static void deprecatedMethod() { //implementation } @Override public String toString() { return "myOwnImplementation"; } }
Annotations (with printflat)
public class Annotations extends java.lang.Object { public Annotations() { super(); } @SuppressWarnings(value = "deprecation") public static void suppressWarnings() { } @Deprecated() public static void deprecatedMethod() { } @Override() public String toString() { return "myOwnImplementation"; } }