src/java.base/share/classes/sun/invoke/anon/AnonymousClassLoader.java

Print this page
rev 12972 : 8140606: Update library code to use internal Unsafe
Reviewed-by: duke


  61  * <li>needs more security work (for safe delegation)</li>
  62  * <li>needs a clearer story about error processing</li>
  63  * <li>patch member references also (use ';' as delimiter char)</li>
  64  * <li>patch method references to (conforming) method handles</li>
  65  * </ul>
  66  *
  67  * @author jrose
  68  * @author Remi Forax
  69  * @see <a href="http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm">
  70  *      http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm</a>
  71  */
  72 
  73 public class AnonymousClassLoader {
  74     final Class<?> hostClass;
  75 
  76     // Privileged constructor.
  77     private AnonymousClassLoader(Class<?> hostClass) {
  78         this.hostClass = hostClass;
  79     }
  80 
  81     public static AnonymousClassLoader make(sun.misc.Unsafe unsafe, Class<?> hostClass) {
  82         if (unsafe == null)  throw new NullPointerException();
  83         return new AnonymousClassLoader(hostClass);
  84     }
  85 
  86     public Class<?> loadClass(byte[] classFile) {
  87         if (defineAnonymousClass == null) {
  88             // no JVM support; try to fake an approximation
  89             try {
  90                 return fakeLoadClass(new ConstantPoolParser(classFile).createPatch());
  91             } catch (InvalidConstantPoolFormatException ee) {
  92                 throw new IllegalArgumentException(ee);
  93             }
  94         }
  95         return loadClass(classFile, null);
  96     }
  97 
  98     public Class<?> loadClass(ConstantPoolPatch classPatch) {
  99         if (defineAnonymousClass == null) {
 100             // no JVM support; try to fake an approximation
 101             return fakeLoadClass(classPatch);


 172         Object[] cpArray;
 173         try {
 174             cpArray = classPatch.getOriginalCP();
 175         } catch (InvalidConstantPoolFormatException ex) {
 176             throw new RuntimeException(ex);
 177         }
 178         int thisClassIndex = classPatch.getParser().getThisClassIndex();
 179         String thisClassName = (String) cpArray[thisClassIndex];
 180         synchronized (AnonymousClassLoader.class) {
 181             thisClassName = thisClassName+"\\|"+(++fakeNameCounter);
 182         }
 183         classPatch.putUTF8(thisClassIndex, thisClassName);
 184         byte[] classFile = null;
 185         return unsafe.defineClass(null, classFile, 0, classFile.length,
 186                                   hostClass.getClassLoader(),
 187                                   hostClass.getProtectionDomain());
 188     }
 189     private static int fakeNameCounter = 99999;
 190 
 191     // ignore two warnings on this line:
 192     private static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
 193     // preceding line requires that this class be on the boot class path
 194 
 195     private static final Method defineAnonymousClass;
 196     static {
 197         Method dac = null;
 198         Class<? extends sun.misc.Unsafe> unsafeClass = unsafe.getClass();
 199         try {
 200             dac = unsafeClass.getMethod("defineAnonymousClass",
 201                                         Class.class,
 202                                         byte[].class,
 203                                         Object[].class);
 204         } catch (Exception ee) {
 205             dac = null;
 206         }
 207         defineAnonymousClass = dac;
 208     }
 209 
 210     private static void noJVMSupport() {
 211         throw new UnsupportedOperationException("no JVM support for anonymous classes");
 212     }
 213 
 214 
 215     private static native Class<?> loadClassInternal(Class<?> hostClass,
 216                                                      byte[] classFile,
 217                                                      Object[] patchArray);
 218 


  61  * <li>needs more security work (for safe delegation)</li>
  62  * <li>needs a clearer story about error processing</li>
  63  * <li>patch member references also (use ';' as delimiter char)</li>
  64  * <li>patch method references to (conforming) method handles</li>
  65  * </ul>
  66  *
  67  * @author jrose
  68  * @author Remi Forax
  69  * @see <a href="http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm">
  70  *      http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm</a>
  71  */
  72 
  73 public class AnonymousClassLoader {
  74     final Class<?> hostClass;
  75 
  76     // Privileged constructor.
  77     private AnonymousClassLoader(Class<?> hostClass) {
  78         this.hostClass = hostClass;
  79     }
  80 
  81     public static AnonymousClassLoader make(jdk.internal.misc.Unsafe unsafe, Class<?> hostClass) {
  82         if (unsafe == null)  throw new NullPointerException();
  83         return new AnonymousClassLoader(hostClass);
  84     }
  85 
  86     public Class<?> loadClass(byte[] classFile) {
  87         if (defineAnonymousClass == null) {
  88             // no JVM support; try to fake an approximation
  89             try {
  90                 return fakeLoadClass(new ConstantPoolParser(classFile).createPatch());
  91             } catch (InvalidConstantPoolFormatException ee) {
  92                 throw new IllegalArgumentException(ee);
  93             }
  94         }
  95         return loadClass(classFile, null);
  96     }
  97 
  98     public Class<?> loadClass(ConstantPoolPatch classPatch) {
  99         if (defineAnonymousClass == null) {
 100             // no JVM support; try to fake an approximation
 101             return fakeLoadClass(classPatch);


 172         Object[] cpArray;
 173         try {
 174             cpArray = classPatch.getOriginalCP();
 175         } catch (InvalidConstantPoolFormatException ex) {
 176             throw new RuntimeException(ex);
 177         }
 178         int thisClassIndex = classPatch.getParser().getThisClassIndex();
 179         String thisClassName = (String) cpArray[thisClassIndex];
 180         synchronized (AnonymousClassLoader.class) {
 181             thisClassName = thisClassName+"\\|"+(++fakeNameCounter);
 182         }
 183         classPatch.putUTF8(thisClassIndex, thisClassName);
 184         byte[] classFile = null;
 185         return unsafe.defineClass(null, classFile, 0, classFile.length,
 186                                   hostClass.getClassLoader(),
 187                                   hostClass.getProtectionDomain());
 188     }
 189     private static int fakeNameCounter = 99999;
 190 
 191     // ignore two warnings on this line:
 192     private static jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
 193     // preceding line requires that this class be on the boot class path
 194 
 195     private static final Method defineAnonymousClass;
 196     static {
 197         Method dac = null;
 198         Class<? extends jdk.internal.misc.Unsafe> unsafeClass = unsafe.getClass();
 199         try {
 200             dac = unsafeClass.getMethod("defineAnonymousClass",
 201                                         Class.class,
 202                                         byte[].class,
 203                                         Object[].class);
 204         } catch (Exception ee) {
 205             dac = null;
 206         }
 207         defineAnonymousClass = dac;
 208     }
 209 
 210     private static void noJVMSupport() {
 211         throw new UnsupportedOperationException("no JVM support for anonymous classes");
 212     }
 213 
 214 
 215     private static native Class<?> loadClassInternal(Class<?> hostClass,
 216                                                      byte[] classFile,
 217                                                      Object[] patchArray);
 218