package com.rc.retroweaver.runtime; import java.util.*; /** * A replacement for the new 1.5 ldc* class literal support. * * In 1.4, class literals were compiled into the following: * * 1) A field: * static java.lang.Class class$<ClassName>; * * 2) A check and method call: * 0: getstatic #7; //Field class$<ClassName>:Ljava/lang/Class; * 3: ifnonnull 18 * 6: ldc #8; //String <ClassName> * 8: invokestatic #9; //Method class$:(Ljava/lang/String;)Ljava/lang/Class; * 11: dup * 12: putstatic #7; //Field class$<ClassName>:Ljava/lang/Class; * 15: goto 21 * 18: getstatic #7; //Field class$<ClassName>:Ljava/lang/Class; * 21: astore_1 * * 3) A method: * static java.lang.Class class$(java.lang.String); * Signature: (Ljava/lang/String;)Ljava/lang/Class; * Code: * 0: aload_0 * 1: invokestatic #1; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class; * 4: areturn * 5: astore_1 * 6: new #3; //class NoClassDefFoundError * 9: dup * 10: aload_1 * 11: invokevirtual #4; //Method java/lang/ClassNotFoundException.getMessage:()Ljava/lang/String; * 14: invokespecial #5; //Method java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V * 17: athrow * Exception table: * from to target type * 0 4 5 Class java/lang/ClassNotFoundException * * In 1.5, ldc was updated to additionally support CONSTANT_Class. All of the 1.4 generated code is * replaced by ldc. In our code, we're going to mimic the 1.4 behavior, but do it without * all of the corresponding code bloat. We're just going to replace the ldc with a call to this * class, which will store the java.lang.Class's in a Map<String,Class>. This does have some drawbacks, * though: * * 1) The map is shared across all threads, requiring synchronization. If this becomes an issue, * we can take care of it by creating a Map per thread. * * 2) Classes had quick access to the class literal, because it was stored in a class static field. * Now, there's the overhead of a O(1) map lookup involved. * * @author Toby Reyelts * */ public class ClassLiteral { private static Map/*<String,Class>*/ classes = new HashMap/*<String,Class>*/(); public static Class getClass( String className ) { synchronized ( classes ) { Class c = ( Class ) classes.get( className ); if ( c != null ) { return c; } } try { Class c = Class.forName( className.replace( '/', '.' ) ); synchronized ( classes ) { classes.put( className, c ); } return c; } catch ( ClassNotFoundException e ) { throw new NoClassDefFoundError( e.getMessage() ); } } }