< prev index next >

src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java

Print this page

 135     protected static <T> Constructor<T> reflectConstructor(Class<T> defc, Class<?>... ptypes) {
 136         try {
 137             return defc.getDeclaredConstructor(ptypes);
 138         } catch (NoSuchMethodException ex) {
 139             throw newIAE(defc.getName()+"("+MethodType.methodType(void.class, ptypes)+")", ex);
 140         }
 141     }
 142 
 143     protected static Field reflectField(Class<?> defc, String name) {
 144         try {
 145             return defc.getDeclaredField(name);
 146         } catch (NoSuchFieldException ex) {
 147             throw newIAE(defc.getName()+"."+name, ex);
 148         }
 149     }
 150 
 151     private static RuntimeException newIAE(String message, Throwable cause) {
 152         return new IllegalArgumentException(message, cause);
 153     }
 154 
 155     private static final Function<Object, Object> CREATE_RESERVATION = new Function<>() {
 156         @Override
 157         public Object apply(Object key) {
 158             return new Object();
 159         }
 160     };


 161 
 162     public final S findSpecies(K key) {
 163         // Note:  Species instantiation may throw VirtualMachineError because of
 164         // code cache overflow.  If this happens the species bytecode may be
 165         // loaded but not linked to its species metadata (with MH's etc).
 166         // That will cause a throw out of Factory.loadSpecies.
 167         //
 168         // In a later attempt to get the same species, the already-loaded
 169         // class will be present in the system dictionary, causing an
 170         // error when the species generator tries to reload it.
 171         // We try to detect this case and link the pre-existing code.
 172         //
 173         // Although it would be better to start fresh by loading a new
 174         // copy, we have to salvage the previously loaded but broken code.
 175         // (As an alternative, we might spin a new class with a new name,
 176         // or use the anonymous class mechanism.)
 177         //
 178         // In the end, as long as everybody goes through this findSpecies method,
 179         // it will ensure only one SpeciesData will be set successfully on a
 180         // concrete class if ever.
 181         // The concrete class is published via SpeciesData instance
 182         // returned here only after the class and species data are linked together.
 183         Object speciesDataOrReservation = cache.computeIfAbsent(key, CREATE_RESERVATION);
 184         // Separating the creation of a placeholder SpeciesData instance above
 185         // from the loading and linking a real one below ensures we can never
 186         // accidentally call computeIfAbsent recursively.
 187         S speciesData;
 188         if (speciesDataOrReservation.getClass() == Object.class) {
 189             synchronized (speciesDataOrReservation) {
 190                 Object existingSpeciesData = cache.get(key);
 191                 if (existingSpeciesData == speciesDataOrReservation) { // won the race
 192                     // create a new SpeciesData...
 193                     speciesData = newSpeciesData(key);
 194                     // load and link it...
 195                     speciesData = factory.loadSpecies(speciesData);
 196                     if (!cache.replace(key, existingSpeciesData, speciesData)) {
 197                         throw newInternalError("Concurrent loadSpecies");
 198                     }
 199                 } else { // lost the race; the retrieved existingSpeciesData is the final
 200                     speciesData = metaType.cast(existingSpeciesData);
 201                 }
 202             }
 203         } else {
 204             speciesData = metaType.cast(speciesDataOrReservation);
 205         }
 206         assert(speciesData != null && speciesData.isResolved());
 207         return speciesData;
 208     }

 135     protected static <T> Constructor<T> reflectConstructor(Class<T> defc, Class<?>... ptypes) {
 136         try {
 137             return defc.getDeclaredConstructor(ptypes);
 138         } catch (NoSuchMethodException ex) {
 139             throw newIAE(defc.getName()+"("+MethodType.methodType(void.class, ptypes)+")", ex);
 140         }
 141     }
 142 
 143     protected static Field reflectField(Class<?> defc, String name) {
 144         try {
 145             return defc.getDeclaredField(name);
 146         } catch (NoSuchFieldException ex) {
 147             throw newIAE(defc.getName()+"."+name, ex);
 148         }
 149     }
 150 
 151     private static RuntimeException newIAE(String message, Throwable cause) {
 152         return new IllegalArgumentException(message, cause);
 153     }
 154 
 155     private static class CacheHolder {
 156         static final Function<Object, Object> CREATE = new Function<>() {
 157             @Override
 158             public Object apply(Object key) {
 159                 return new CacheHolder();
 160             }
 161         };
 162     }
 163 
 164     public final S findSpecies(K key) {
 165         // Note:  Species instantiation may throw VirtualMachineError because of
 166         // code cache overflow.  If this happens the species bytecode may be
 167         // loaded but not linked to its species metadata (with MH's etc).
 168         // That will cause a throw out of Factory.loadSpecies.
 169         //
 170         // In a later attempt to get the same species, the already-loaded
 171         // class will be present in the system dictionary, causing an
 172         // error when the species generator tries to reload it.
 173         // We try to detect this case and link the pre-existing code.
 174         //
 175         // Although it would be better to start fresh by loading a new
 176         // copy, we have to salvage the previously loaded but broken code.
 177         // (As an alternative, we might spin a new class with a new name,
 178         // or use the anonymous class mechanism.)
 179         //
 180         // In the end, as long as everybody goes through this findSpecies method,
 181         // it will ensure only one SpeciesData will be set successfully on a
 182         // concrete class if ever.
 183         // The concrete class is published via SpeciesData instance
 184         // returned here only after the class and species data are linked together.
 185         Object speciesDataOrReservation = cache.computeIfAbsent(key, CacheHolder.CREATE);
 186         // Separating the creation of a placeholder SpeciesData instance above
 187         // from the loading and linking a real one below ensures we can never
 188         // accidentally call computeIfAbsent recursively.
 189         S speciesData;
 190         if (speciesDataOrReservation.getClass() == CacheHolder.class) {
 191             synchronized (speciesDataOrReservation) {
 192                 Object existingSpeciesData = cache.get(key);
 193                 if (existingSpeciesData == speciesDataOrReservation) { // won the race
 194                     // create a new SpeciesData...
 195                     speciesData = newSpeciesData(key);
 196                     // load and link it...
 197                     speciesData = factory.loadSpecies(speciesData);
 198                     if (!cache.replace(key, existingSpeciesData, speciesData)) {
 199                         throw newInternalError("Concurrent loadSpecies");
 200                     }
 201                 } else { // lost the race; the retrieved existingSpeciesData is the final
 202                     speciesData = metaType.cast(existingSpeciesData);
 203                 }
 204             }
 205         } else {
 206             speciesData = metaType.cast(speciesDataOrReservation);
 207         }
 208         assert(speciesData != null && speciesData.isResolved());
 209         return speciesData;
 210     }
< prev index next >