10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.invoke; 27 28 import jdk.internal.org.objectweb.asm.*; 29 import sun.invoke.util.BytecodeDescriptor; 30 import jdk.internal.misc.Unsafe; 31 import sun.security.action.GetPropertyAction; 32 import sun.security.action.GetBooleanAction; 33 34 import java.io.FilePermission; 35 import java.io.Serializable; 36 import java.lang.reflect.Constructor; 37 import java.security.AccessController; 38 import java.security.PrivilegedAction; 39 import java.util.LinkedHashSet; 40 import java.util.concurrent.atomic.AtomicInteger; 41 import java.util.PropertyPermission; 42 import java.util.Set; 43 44 import static jdk.internal.org.objectweb.asm.Opcodes.*; 45 46 /** 47 * Lambda metafactory implementation which dynamically creates an 48 * inner-class-like class per lambda callsite. 49 * 50 * @see LambdaMetafactory 51 */ 52 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { 53 private static final Unsafe UNSAFE = Unsafe.getUnsafe(); 54 55 private static final int CLASSFILE_VERSION = 52; 56 private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE); 57 private static final String JAVA_LANG_OBJECT = "java/lang/Object"; 58 private static final String NAME_CTOR = "<init>"; 59 private static final String NAME_FACTORY = "get$Lambda"; 60 61 //Serialization support 62 private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda"; 63 private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException"; 64 private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;"; 65 private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V"; 66 private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V"; 67 private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace"; 68 private static final String NAME_METHOD_READ_OBJECT = "readObject"; 69 private static final String NAME_METHOD_WRITE_OBJECT = "writeObject"; 70 71 private static final String DESCR_CLASS = "Ljava/lang/Class;"; 72 private static final String DESCR_STRING = "Ljava/lang/String;"; 73 private static final String DESCR_OBJECT = "Ljava/lang/Object;"; 74 private static final String DESCR_CTOR_SERIALIZED_LAMBDA 75 = "(" + DESCR_CLASS + DESCR_STRING + DESCR_STRING + DESCR_STRING + "I" 76 + DESCR_STRING + DESCR_STRING + DESCR_STRING + DESCR_STRING + "[" + DESCR_OBJECT + ")V"; 77 78 private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION = "(Ljava/lang/String;)V"; 79 private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION}; 80 81 private static final String DESCR_HIDDEN = "Ljdk/internal/vm/annotation/Hidden;"; 82 83 private static final String[] EMPTY_STRING_ARRAY = new String[0]; 84 85 // Used to ensure that each spun class name is unique 86 private static final AtomicInteger counter = new AtomicInteger(0); 87 88 // For dumping generated classes to disk, for debugging purposes 89 private static final ProxyClassesDumper dumper; 90 91 private static final boolean disableEagerInitialization; 92 93 static { 94 final String dumpProxyClassesKey = "jdk.internal.lambda.dumpProxyClasses"; 95 String dumpPath = GetPropertyAction.privilegedGetProperty(dumpProxyClassesKey); 96 dumper = (null == dumpPath) ? null : ProxyClassesDumper.getInstance(dumpPath); 97 98 final String disableEagerInitializationKey = "jdk.internal.lambda.disableEagerInitialization"; 99 disableEagerInitialization = GetBooleanAction.privilegedGetProperty(disableEagerInitializationKey); 100 } 101 102 // See context values in AbstractValidatingLambdaMetafactory 146 * @throws LambdaConversionException If any of the meta-factory protocol 147 * invariants are violated 148 */ 149 public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, 150 MethodType invokedType, 151 String samMethodName, 152 MethodType samMethodType, 153 MethodHandle implMethod, 154 MethodType instantiatedMethodType, 155 boolean isSerializable, 156 Class<?>[] markerInterfaces, 157 MethodType[] additionalBridges) 158 throws LambdaConversionException { 159 super(caller, invokedType, samMethodName, samMethodType, 160 implMethod, instantiatedMethodType, 161 isSerializable, markerInterfaces, additionalBridges); 162 implMethodClassName = implClass.getName().replace('.', '/'); 163 implMethodName = implInfo.getName(); 164 implMethodDesc = implInfo.getMethodType().toMethodDescriptorString(); 165 constructorType = invokedType.changeReturnType(Void.TYPE); 166 lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet(); 167 cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); 168 int parameterCount = invokedType.parameterCount(); 169 if (parameterCount > 0) { 170 argNames = new String[parameterCount]; 171 argDescs = new String[parameterCount]; 172 for (int i = 0; i < parameterCount; i++) { 173 argNames[i] = "arg$" + (i + 1); 174 argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i)); 175 } 176 } else { 177 argNames = argDescs = EMPTY_STRING_ARRAY; 178 } 179 } 180 181 /** 182 * Build the CallSite. Generate a class file which implements the functional 183 * interface, define the class, if there are no parameters create an instance 184 * of the class which the CallSite will return, otherwise, generate handles 185 * which will call the class' constructor. 186 * 187 * @return a CallSite, which, when invoked, will return an instance of the 188 * functional interface 189 * @throws ReflectiveOperationException 190 * @throws LambdaConversionException If properly formed functional interface 191 * is not found 192 */ 193 @Override 194 CallSite buildCallSite() throws LambdaConversionException { 195 final Class<?> innerClass = spinInnerClass(); 196 if (invokedType.parameterCount() == 0 && !disableEagerInitialization) { 197 // In the case of a non-capturing lambda, we optimize linkage by pre-computing a single instance, 198 // unless we've suppressed eager initialization 199 final Constructor<?>[] ctrs = AccessController.doPrivileged( 200 new PrivilegedAction<>() { 201 @Override 202 public Constructor<?>[] run() { 203 Constructor<?>[] ctrs = innerClass.getDeclaredConstructors(); 204 if (ctrs.length == 1) { 205 // The lambda implementing inner class constructor is private, set 206 // it accessible (by us) before creating the constant sole instance 207 ctrs[0].setAccessible(true); 208 } 209 return ctrs; 210 } 211 }); 212 if (ctrs.length != 1) { 213 throw new LambdaConversionException("Expected one lambda constructor for " 214 + innerClass.getCanonicalName() + ", got " + ctrs.length); 215 } 216 217 try { 218 Object inst = ctrs[0].newInstance(); 219 return new ConstantCallSite(MethodHandles.constant(samBase, inst)); 220 } 221 catch (ReflectiveOperationException e) { 222 throw new LambdaConversionException("Exception instantiating lambda object", e); 223 } 224 } else { 225 try { 226 if (!disableEagerInitialization) { 227 UNSAFE.ensureClassInitialized(innerClass); 228 } 229 return new ConstantCallSite( 230 MethodHandles.Lookup.IMPL_LOOKUP 231 .findStatic(innerClass, NAME_FACTORY, invokedType)); 232 } 233 catch (ReflectiveOperationException e) { 234 throw new LambdaConversionException("Exception finding constructor", e); 235 } 236 } 237 } 238 239 /** 240 * Generate a class file which implements the functional 241 * interface, define and return the class. 242 * 243 * @implNote The class that is generated does not include signature 244 * information for exceptions that may be present on the SAM method. 245 * This is to reduce classfile size, and is harmless as checked exceptions 246 * are erased anyway, no one will ever compile against this classfile, 247 * and we make no guarantees about the reflective properties of lambda 248 * objects. 249 * 250 * @return a Class which implements the functional interface 251 * @throws LambdaConversionException If properly formed functional interface 252 * is not found 253 */ 266 accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface); 267 } 268 interfaces = itfs.toArray(new String[itfs.size()]); 269 } 270 271 cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC, 272 lambdaClassName, null, 273 JAVA_LANG_OBJECT, interfaces); 274 275 // Generate final fields to be filled in by constructor 276 for (int i = 0; i < argDescs.length; i++) { 277 FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, 278 argNames[i], 279 argDescs[i], 280 null, null); 281 fv.visitEnd(); 282 } 283 284 generateConstructor(); 285 286 if (invokedType.parameterCount() != 0 || disableEagerInitialization) { 287 generateFactory(); 288 } 289 290 // Forward the SAM method 291 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName, 292 samMethodType.toMethodDescriptorString(), null, null); 293 mv.visitAnnotation(DESCR_HIDDEN, true); 294 new ForwardingMethodGenerator(mv).generate(samMethodType); 295 296 // Forward the bridges 297 if (additionalBridges != null) { 298 for (MethodType mt : additionalBridges) { 299 mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName, 300 mt.toMethodDescriptorString(), null, null); 301 mv.visitAnnotation(DESCR_HIDDEN, true); 302 new ForwardingMethodGenerator(mv).generate(mt); 303 } 304 } 305 306 if (isSerializable) 307 generateSerializationFriendlyMethods(); 308 else if (accidentallySerializable) 309 generateSerializationHostileMethods(); 310 311 cw.visitEnd(); 312 313 // Define the generated class in this VM. 314 315 final byte[] classBytes = cw.toByteArray(); 316 317 // If requested, dump out to a file for debugging purposes 318 if (dumper != null) { 319 AccessController.doPrivileged(new PrivilegedAction<>() { 320 @Override 321 public Void run() { 322 dumper.dumpClass(lambdaClassName, classBytes); 323 return null; 324 } 325 }, null, 326 new FilePermission("<<ALL FILES>>", "read, write"), 327 // createDirectories may need it 328 new PropertyPermission("user.dir", "read")); 329 } 330 331 return UNSAFE.defineAnonymousClass(targetClass, classBytes, null); 332 } 333 334 /** 335 * Generate the factory method for the class 336 */ 337 private void generateFactory() { 338 MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null); 339 m.visitCode(); 340 m.visitTypeInsn(NEW, lambdaClassName); 341 m.visitInsn(Opcodes.DUP); 342 int parameterCount = invokedType.parameterCount(); 343 for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) { 344 Class<?> argType = invokedType.parameterType(typeIndex); 345 m.visitVarInsn(getLoadOpcode(argType), varIndex); 346 varIndex += getParameterSize(argType); 347 } 348 m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false); 349 m.visitInsn(ARETURN); 350 m.visitMaxs(-1, -1); 351 m.visitEnd(); 352 } 353 354 /** 355 * Generate the constructor for the class 356 */ 357 private void generateConstructor() { 358 // Generate constructor 359 MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, 360 constructorType.toMethodDescriptorString(), null, null); 361 ctor.visitCode(); 362 ctor.visitVarInsn(ALOAD, 0); 363 ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR, 364 METHOD_DESCRIPTOR_VOID, false); 365 int parameterCount = invokedType.parameterCount(); 366 for (int i = 0, lvIndex = 0; i < parameterCount; i++) { 367 ctor.visitVarInsn(ALOAD, 0); 368 Class<?> argType = invokedType.parameterType(i); 369 ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1); 370 lvIndex += getParameterSize(argType); 371 ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]); | 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.invoke; 27 28 import jdk.internal.org.objectweb.asm.*; 29 import sun.invoke.util.BytecodeDescriptor; 30 import sun.security.action.GetPropertyAction; 31 import sun.security.action.GetBooleanAction; 32 33 import java.io.FilePermission; 34 import java.io.Serializable; 35 import java.lang.invoke.MethodHandles.Lookup; 36 import java.lang.reflect.Constructor; 37 import java.security.AccessController; 38 import java.security.PrivilegedAction; 39 import java.util.LinkedHashSet; 40 import java.util.concurrent.atomic.AtomicInteger; 41 import java.util.PropertyPermission; 42 import java.util.Set; 43 44 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE; 45 import static jdk.internal.org.objectweb.asm.Opcodes.*; 46 47 /** 48 * Lambda metafactory implementation which dynamically creates an 49 * inner-class-like class per lambda callsite. 50 * 51 * @see LambdaMetafactory 52 */ 53 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { 54 private static final int CLASSFILE_VERSION = 52; 55 private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE); 56 private static final String JAVA_LANG_OBJECT = "java/lang/Object"; 57 private static final String NAME_CTOR = "<init>"; 58 59 //Serialization support 60 private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda"; 61 private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException"; 62 private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;"; 63 private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V"; 64 private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V"; 65 private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace"; 66 private static final String NAME_METHOD_READ_OBJECT = "readObject"; 67 private static final String NAME_METHOD_WRITE_OBJECT = "writeObject"; 68 69 private static final String DESCR_CLASS = "Ljava/lang/Class;"; 70 private static final String DESCR_STRING = "Ljava/lang/String;"; 71 private static final String DESCR_OBJECT = "Ljava/lang/Object;"; 72 private static final String DESCR_CTOR_SERIALIZED_LAMBDA 73 = "(" + DESCR_CLASS + DESCR_STRING + DESCR_STRING + DESCR_STRING + "I" 74 + DESCR_STRING + DESCR_STRING + DESCR_STRING + DESCR_STRING + "[" + DESCR_OBJECT + ")V"; 75 76 private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION = "(Ljava/lang/String;)V"; 77 private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION}; 78 79 private static final String[] EMPTY_STRING_ARRAY = new String[0]; 80 81 // Used to ensure that each spun class name is unique 82 private static final AtomicInteger counter = new AtomicInteger(0); 83 84 // For dumping generated classes to disk, for debugging purposes 85 private static final ProxyClassesDumper dumper; 86 87 private static final boolean disableEagerInitialization; 88 89 static { 90 final String dumpProxyClassesKey = "jdk.internal.lambda.dumpProxyClasses"; 91 String dumpPath = GetPropertyAction.privilegedGetProperty(dumpProxyClassesKey); 92 dumper = (null == dumpPath) ? null : ProxyClassesDumper.getInstance(dumpPath); 93 94 final String disableEagerInitializationKey = "jdk.internal.lambda.disableEagerInitialization"; 95 disableEagerInitialization = GetBooleanAction.privilegedGetProperty(disableEagerInitializationKey); 96 } 97 98 // See context values in AbstractValidatingLambdaMetafactory 142 * @throws LambdaConversionException If any of the meta-factory protocol 143 * invariants are violated 144 */ 145 public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, 146 MethodType invokedType, 147 String samMethodName, 148 MethodType samMethodType, 149 MethodHandle implMethod, 150 MethodType instantiatedMethodType, 151 boolean isSerializable, 152 Class<?>[] markerInterfaces, 153 MethodType[] additionalBridges) 154 throws LambdaConversionException { 155 super(caller, invokedType, samMethodName, samMethodType, 156 implMethod, instantiatedMethodType, 157 isSerializable, markerInterfaces, additionalBridges); 158 implMethodClassName = implClass.getName().replace('.', '/'); 159 implMethodName = implInfo.getName(); 160 implMethodDesc = implInfo.getMethodType().toMethodDescriptorString(); 161 constructorType = invokedType.changeReturnType(Void.TYPE); 162 lambdaClassName = lambdaClassName(targetClass); 163 cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); 164 int parameterCount = invokedType.parameterCount(); 165 if (parameterCount > 0) { 166 argNames = new String[parameterCount]; 167 argDescs = new String[parameterCount]; 168 for (int i = 0; i < parameterCount; i++) { 169 argNames[i] = "arg$" + (i + 1); 170 argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i)); 171 } 172 } else { 173 argNames = argDescs = EMPTY_STRING_ARRAY; 174 } 175 } 176 177 private static String lambdaClassName(Class<?> targetClass) { 178 String name = targetClass.getName(); 179 if (targetClass.isHiddenClass()) { 180 // use the original class name 181 name = name.replace('/', '_'); 182 } 183 return name.replace('.', '/') + "$$Lambda$" + counter.incrementAndGet(); 184 } 185 186 /** 187 * Build the CallSite. Generate a class file which implements the functional 188 * interface, define the class, if there are no parameters create an instance 189 * of the class which the CallSite will return, otherwise, generate handles 190 * which will call the class' constructor. 191 * 192 * @return a CallSite, which, when invoked, will return an instance of the 193 * functional interface 194 * @throws ReflectiveOperationException 195 * @throws LambdaConversionException If properly formed functional interface 196 * is not found 197 */ 198 @Override 199 CallSite buildCallSite() throws LambdaConversionException { 200 final Class<?> innerClass = spinInnerClass(); 201 assert innerClass.isHiddenClass() : innerClass.toString(); 202 if (invokedType.parameterCount() == 0 && !disableEagerInitialization) { 203 // In the case of a non-capturing lambda, we optimize linkage by pre-computing a single instance, 204 // unless we've suppressed eager initialization 205 final Constructor<?>[] ctrs = AccessController.doPrivileged( 206 new PrivilegedAction<>() { 207 @Override 208 public Constructor<?>[] run() { 209 Constructor<?>[] ctrs = innerClass.getDeclaredConstructors(); 210 if (ctrs.length == 1) { 211 // The lambda implementing inner class constructor is private, set 212 // it accessible (by us) before creating the constant sole instance 213 ctrs[0].setAccessible(true); 214 } 215 return ctrs; 216 } 217 }); 218 if (ctrs.length != 1) { 219 throw new LambdaConversionException("Expected one lambda constructor for " 220 + innerClass.getCanonicalName() + ", got " + ctrs.length); 221 } 222 223 try { 224 Object inst = ctrs[0].newInstance(); 225 return new ConstantCallSite(MethodHandles.constant(samBase, inst)); 226 } catch (ReflectiveOperationException e) { 227 throw new LambdaConversionException("Exception instantiating lambda object", e); 228 } 229 } else { 230 try { 231 MethodHandle mh = caller.findConstructor(innerClass, invokedType.changeReturnType(void.class)); 232 return new ConstantCallSite(mh.asType(invokedType)); 233 } catch (ReflectiveOperationException e) { 234 throw new LambdaConversionException("Exception finding constructor", e); 235 } 236 } 237 } 238 239 /** 240 * Generate a class file which implements the functional 241 * interface, define and return the class. 242 * 243 * @implNote The class that is generated does not include signature 244 * information for exceptions that may be present on the SAM method. 245 * This is to reduce classfile size, and is harmless as checked exceptions 246 * are erased anyway, no one will ever compile against this classfile, 247 * and we make no guarantees about the reflective properties of lambda 248 * objects. 249 * 250 * @return a Class which implements the functional interface 251 * @throws LambdaConversionException If properly formed functional interface 252 * is not found 253 */ 266 accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface); 267 } 268 interfaces = itfs.toArray(new String[itfs.size()]); 269 } 270 271 cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC, 272 lambdaClassName, null, 273 JAVA_LANG_OBJECT, interfaces); 274 275 // Generate final fields to be filled in by constructor 276 for (int i = 0; i < argDescs.length; i++) { 277 FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, 278 argNames[i], 279 argDescs[i], 280 null, null); 281 fv.visitEnd(); 282 } 283 284 generateConstructor(); 285 286 // Forward the SAM method 287 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName, 288 samMethodType.toMethodDescriptorString(), null, null); 289 new ForwardingMethodGenerator(mv).generate(samMethodType); 290 291 // Forward the bridges 292 if (additionalBridges != null) { 293 for (MethodType mt : additionalBridges) { 294 mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName, 295 mt.toMethodDescriptorString(), null, null); 296 new ForwardingMethodGenerator(mv).generate(mt); 297 } 298 } 299 300 if (isSerializable) 301 generateSerializationFriendlyMethods(); 302 else if (accidentallySerializable) 303 generateSerializationHostileMethods(); 304 305 cw.visitEnd(); 306 307 // Define the generated class in this VM. 308 309 final byte[] classBytes = cw.toByteArray(); 310 // If requested, dump out to a file for debugging purposes 311 if (dumper != null) { 312 AccessController.doPrivileged(new PrivilegedAction<>() { 313 @Override 314 public Void run() { 315 dumper.dumpClass(lambdaClassName, classBytes); 316 return null; 317 } 318 }, null, 319 new FilePermission("<<ALL FILES>>", "read, write"), 320 // createDirectories may need it 321 new PropertyPermission("user.dir", "read")); 322 } 323 try { 324 // this class is linked at the indy callsite; so define a hidden nestmate 325 return caller.defineHiddenClass(classBytes, !disableEagerInitialization, NESTMATE).lookupClass(); 326 } catch (IllegalAccessException e) { 327 throw new LambdaConversionException("Exception defining lambda proxy class", e); 328 } 329 } 330 331 /** 332 * Generate the constructor for the class 333 */ 334 private void generateConstructor() { 335 // Generate constructor 336 MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, 337 constructorType.toMethodDescriptorString(), null, null); 338 ctor.visitCode(); 339 ctor.visitVarInsn(ALOAD, 0); 340 ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR, 341 METHOD_DESCRIPTOR_VOID, false); 342 int parameterCount = invokedType.parameterCount(); 343 for (int i = 0, lvIndex = 0; i < parameterCount; i++) { 344 ctor.visitVarInsn(ALOAD, 0); 345 Class<?> argType = invokedType.parameterType(i); 346 ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1); 347 lvIndex += getParameterSize(argType); 348 ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]); |