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
33 import java.io.FilePermission;
34 import java.io.Serializable;
35 import java.lang.reflect.Constructor;
36 import java.security.AccessController;
37 import java.security.PrivilegedAction;
38 import java.util.LinkedHashSet;
39 import java.util.concurrent.atomic.AtomicInteger;
40 import java.util.PropertyPermission;
41 import java.util.Set;
42
43 import static jdk.internal.org.objectweb.asm.Opcodes.*;
44
45 /**
46 * Lambda metafactory implementation which dynamically creates an
47 * inner-class-like class per lambda callsite.
48 *
49 * @see LambdaMetafactory
50 */
51 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
52 private static final Unsafe UNSAFE = Unsafe.getUnsafe();
53
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 private static final String NAME_FACTORY = "get$Lambda";
59
60 //Serialization support
61 private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
62 private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
63 private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
64 private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
65 private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
66 private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
67 private static final String NAME_METHOD_READ_OBJECT = "readObject";
68 private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
69
70 private static final String DESCR_CLASS = "Ljava/lang/Class;";
71 private static final String DESCR_STRING = "Ljava/lang/String;";
72 private static final String DESCR_OBJECT = "Ljava/lang/Object;";
73 private static final String DESCR_CTOR_SERIALIZED_LAMBDA
74 = "(" + DESCR_CLASS + DESCR_STRING + DESCR_STRING + DESCR_STRING + "I"
75 + DESCR_STRING + DESCR_STRING + DESCR_STRING + DESCR_STRING + "[" + DESCR_OBJECT + ")V";
76
77 private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION = "(Ljava/lang/String;)V";
78 private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION};
79
80 private static final String DESCR_HIDDEN = "Ljdk/internal/vm/annotation/Hidden;";
81
82 private static final String[] EMPTY_STRING_ARRAY = new String[0];
83
84 // Used to ensure that each spun class name is unique
85 private static final AtomicInteger counter = new AtomicInteger(0);
86
87 // For dumping generated classes to disk, for debugging purposes
88 private static final ProxyClassesDumper dumper;
89
90 static {
91 final String key = "jdk.internal.lambda.dumpProxyClasses";
92 String path = GetPropertyAction.privilegedGetProperty(key);
93 dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path);
94 }
95
96 // See context values in AbstractValidatingLambdaMetafactory
97 private final String implMethodClassName; // Name of type containing implementation "CC"
98 private final String implMethodName; // Name of implementation method "impl"
99 private final String implMethodDesc; // Type descriptor for implementation methods "(I)Ljava/lang/String;"
100 private final MethodType constructorType; // Generated class constructor type "(CC)void"
101 private final ClassWriter cw; // ASM class writer
102 private final String[] argNames; // Generated names for the constructor arguments
103 private final String[] argDescs; // Type descriptors for the constructor arguments
104 private final String lambdaClassName; // Generated name for the generated class "X$$Lambda$1"
105
106 /**
107 * General meta-factory constructor, supporting both standard cases and
108 * allowing for uncommon options such as serialization or bridging.
109 *
110 * @param caller Stacked automatically by VM; represents a lookup context
111 * with the accessibility privileges of the caller.
112 * @param invokedType Stacked automatically by VM; the signature of the
113 * invoked method, which includes the expected static
163 if (parameterCount > 0) {
164 argNames = new String[parameterCount];
165 argDescs = new String[parameterCount];
166 for (int i = 0; i < parameterCount; i++) {
167 argNames[i] = "arg$" + (i + 1);
168 argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i));
169 }
170 } else {
171 argNames = argDescs = EMPTY_STRING_ARRAY;
172 }
173 }
174
175 /**
176 * Build the CallSite. Generate a class file which implements the functional
177 * interface, define the class, if there are no parameters create an instance
178 * of the class which the CallSite will return, otherwise, generate handles
179 * which will call the class' constructor.
180 *
181 * @return a CallSite, which, when invoked, will return an instance of the
182 * functional interface
183 * @throws ReflectiveOperationException
184 * @throws LambdaConversionException If properly formed functional interface
185 * is not found
186 */
187 @Override
188 CallSite buildCallSite() throws LambdaConversionException {
189 final Class<?> innerClass = spinInnerClass();
190 if (invokedType.parameterCount() == 0) {
191 final Constructor<?>[] ctrs = AccessController.doPrivileged(
192 new PrivilegedAction<>() {
193 @Override
194 public Constructor<?>[] run() {
195 Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
196 if (ctrs.length == 1) {
197 // The lambda implementing inner class constructor is private, set
198 // it accessible (by us) before creating the constant sole instance
199 ctrs[0].setAccessible(true);
200 }
201 return ctrs;
202 }
203 });
204 if (ctrs.length != 1) {
205 throw new LambdaConversionException("Expected one lambda constructor for "
206 + innerClass.getCanonicalName() + ", got " + ctrs.length);
207 }
208
209 try {
210 Object inst = ctrs[0].newInstance();
211 return new ConstantCallSite(MethodHandles.constant(samBase, inst));
212 }
213 catch (ReflectiveOperationException e) {
214 throw new LambdaConversionException("Exception instantiating lambda object", e);
215 }
216 } else {
217 try {
218 UNSAFE.ensureClassInitialized(innerClass);
219 return new ConstantCallSite(
220 MethodHandles.Lookup.IMPL_LOOKUP
221 .findStatic(innerClass, NAME_FACTORY, invokedType));
222 }
223 catch (ReflectiveOperationException e) {
224 throw new LambdaConversionException("Exception finding constructor", e);
225 }
226 }
227 }
228
229 /**
230 * Generate a class file which implements the functional
231 * interface, define and return the class.
232 *
233 * @implNote The class that is generated does not include signature
234 * information for exceptions that may be present on the SAM method.
235 * This is to reduce classfile size, and is harmless as checked exceptions
236 * are erased anyway, no one will ever compile against this classfile,
237 * and we make no guarantees about the reflective properties of lambda
238 * objects.
239 *
240 * @return a Class which implements the functional interface
241 * @throws LambdaConversionException If properly formed functional interface
242 * is not found
243 */
244 private Class<?> spinInnerClass() throws LambdaConversionException {
245 String[] interfaces;
255 itfs.add(markerInterface.getName().replace('.', '/'));
256 accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface);
257 }
258 interfaces = itfs.toArray(new String[itfs.size()]);
259 }
260
261 cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
262 lambdaClassName, null,
263 JAVA_LANG_OBJECT, interfaces);
264
265 // Generate final fields to be filled in by constructor
266 for (int i = 0; i < argDescs.length; i++) {
267 FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL,
268 argNames[i],
269 argDescs[i],
270 null, null);
271 fv.visitEnd();
272 }
273
274 generateConstructor();
275
276 if (invokedType.parameterCount() != 0) {
277 generateFactory();
278 }
279
280 // Forward the SAM method
281 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
282 samMethodType.toMethodDescriptorString(), null, null);
283 mv.visitAnnotation(DESCR_HIDDEN, true);
284 new ForwardingMethodGenerator(mv).generate(samMethodType);
285
286 // Forward the bridges
287 if (additionalBridges != null) {
288 for (MethodType mt : additionalBridges) {
289 mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
290 mt.toMethodDescriptorString(), null, null);
291 mv.visitAnnotation(DESCR_HIDDEN, true);
292 new ForwardingMethodGenerator(mv).generate(mt);
293 }
294 }
295
296 if (isSerializable)
305 final byte[] classBytes = cw.toByteArray();
306
307 // If requested, dump out to a file for debugging purposes
308 if (dumper != null) {
309 AccessController.doPrivileged(new PrivilegedAction<>() {
310 @Override
311 public Void run() {
312 dumper.dumpClass(lambdaClassName, classBytes);
313 return null;
314 }
315 }, null,
316 new FilePermission("<<ALL FILES>>", "read, write"),
317 // createDirectories may need it
318 new PropertyPermission("user.dir", "read"));
319 }
320
321 return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
322 }
323
324 /**
325 * Generate the factory method for the class
326 */
327 private void generateFactory() {
328 MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null);
329 m.visitCode();
330 m.visitTypeInsn(NEW, lambdaClassName);
331 m.visitInsn(Opcodes.DUP);
332 int parameterCount = invokedType.parameterCount();
333 for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) {
334 Class<?> argType = invokedType.parameterType(typeIndex);
335 m.visitVarInsn(getLoadOpcode(argType), varIndex);
336 varIndex += getParameterSize(argType);
337 }
338 m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false);
339 m.visitInsn(ARETURN);
340 m.visitMaxs(-1, -1);
341 m.visitEnd();
342 }
343
344 /**
345 * Generate the constructor for the class
346 */
347 private void generateConstructor() {
348 // Generate constructor
349 MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,
350 constructorType.toMethodDescriptorString(), null, null);
351 ctor.visitCode();
352 ctor.visitVarInsn(ALOAD, 0);
353 ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR,
354 METHOD_DESCRIPTOR_VOID, false);
355 int parameterCount = invokedType.parameterCount();
356 for (int i = 0, lvIndex = 0; i < parameterCount; i++) {
357 ctor.visitVarInsn(ALOAD, 0);
358 Class<?> argType = invokedType.parameterType(i);
359 ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
360 lvIndex += getParameterSize(argType);
361 ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]);
|
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.GetBooleanAction;
32 import sun.security.action.GetPropertyAction;
33
34 import java.io.FilePermission;
35 import java.io.Serializable;
36 import java.security.AccessController;
37 import java.security.PrivilegedAction;
38 import java.util.LinkedHashSet;
39 import java.util.concurrent.atomic.AtomicInteger;
40 import java.util.PropertyPermission;
41 import java.util.Set;
42
43 import static jdk.internal.org.objectweb.asm.Opcodes.*;
44
45 /**
46 * Lambda metafactory implementation which dynamically creates an
47 * inner-class-like class per lambda callsite.
48 *
49 * @see LambdaMetafactory
50 */
51 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
52 private static final Unsafe UNSAFE = Unsafe.getUnsafe();
53
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 private static final String NAME_FACTORY = "get$Lambda";
59 private static final String LAMBDA_INSTANCE_FIELD = "LAMBDA_INSTANCE$";
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 // disable optimization that eagerly initializes lambdas
92 private static final boolean disableEagerInitialization;
93
94 static {
95 final String dumpKey = "jdk.internal.lambda.dumpProxyClasses";
96 String path = GetPropertyAction.privilegedGetProperty(dumpKey);
97 dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path);
98
99 final String disableEagerInitializationKey = "jdk.internal.lambda.disableEagerInitialization";
100 disableEagerInitialization = GetBooleanAction.privilegedGetProperty(disableEagerInitializationKey);
101 }
102
103 // See context values in AbstractValidatingLambdaMetafactory
104 private final String implMethodClassName; // Name of type containing implementation "CC"
105 private final String implMethodName; // Name of implementation method "impl"
106 private final String implMethodDesc; // Type descriptor for implementation methods "(I)Ljava/lang/String;"
107 private final MethodType constructorType; // Generated class constructor type "(CC)void"
108 private final ClassWriter cw; // ASM class writer
109 private final String[] argNames; // Generated names for the constructor arguments
110 private final String[] argDescs; // Type descriptors for the constructor arguments
111 private final String lambdaClassName; // Generated name for the generated class "X$$Lambda$1"
112
113 /**
114 * General meta-factory constructor, supporting both standard cases and
115 * allowing for uncommon options such as serialization or bridging.
116 *
117 * @param caller Stacked automatically by VM; represents a lookup context
118 * with the accessibility privileges of the caller.
119 * @param invokedType Stacked automatically by VM; the signature of the
120 * invoked method, which includes the expected static
170 if (parameterCount > 0) {
171 argNames = new String[parameterCount];
172 argDescs = new String[parameterCount];
173 for (int i = 0; i < parameterCount; i++) {
174 argNames[i] = "arg$" + (i + 1);
175 argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i));
176 }
177 } else {
178 argNames = argDescs = EMPTY_STRING_ARRAY;
179 }
180 }
181
182 /**
183 * Build the CallSite. Generate a class file which implements the functional
184 * interface, define the class, if there are no parameters create an instance
185 * of the class which the CallSite will return, otherwise, generate handles
186 * which will call the class' constructor.
187 *
188 * @return a CallSite, which, when invoked, will return an instance of the
189 * functional interface
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 try {
197 if (!disableEagerInitialization) {
198 UNSAFE.ensureClassInitialized(innerClass);
199 }
200 MethodHandle lambdaHandle = invokedType.parameterCount() == 0
201 ? MethodHandles.Lookup.IMPL_LOOKUP.findStaticGetter(innerClass, LAMBDA_INSTANCE_FIELD, invokedType.returnType())
202 : MethodHandles.Lookup.IMPL_LOOKUP.findStatic(innerClass, NAME_FACTORY, invokedType);
203
204 return new ConstantCallSite(lambdaHandle);
205 }
206 catch (ReflectiveOperationException e) {
207 throw new LambdaConversionException("Exception finding lambda ", e);
208 }
209 }
210
211 /**
212 * Generate a class file which implements the functional
213 * interface, define and return the class.
214 *
215 * @implNote The class that is generated does not include signature
216 * information for exceptions that may be present on the SAM method.
217 * This is to reduce classfile size, and is harmless as checked exceptions
218 * are erased anyway, no one will ever compile against this classfile,
219 * and we make no guarantees about the reflective properties of lambda
220 * objects.
221 *
222 * @return a Class which implements the functional interface
223 * @throws LambdaConversionException If properly formed functional interface
224 * is not found
225 */
226 private Class<?> spinInnerClass() throws LambdaConversionException {
227 String[] interfaces;
237 itfs.add(markerInterface.getName().replace('.', '/'));
238 accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface);
239 }
240 interfaces = itfs.toArray(new String[itfs.size()]);
241 }
242
243 cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
244 lambdaClassName, null,
245 JAVA_LANG_OBJECT, interfaces);
246
247 // Generate final fields to be filled in by constructor
248 for (int i = 0; i < argDescs.length; i++) {
249 FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL,
250 argNames[i],
251 argDescs[i],
252 null, null);
253 fv.visitEnd();
254 }
255
256 generateConstructor();
257 if (invokedType.parameterCount() == 0) {
258 generateStaticField();
259 } else {
260 generateFactory();
261 }
262
263 // Forward the SAM method
264 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
265 samMethodType.toMethodDescriptorString(), null, null);
266 mv.visitAnnotation(DESCR_HIDDEN, true);
267 new ForwardingMethodGenerator(mv).generate(samMethodType);
268
269 // Forward the bridges
270 if (additionalBridges != null) {
271 for (MethodType mt : additionalBridges) {
272 mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
273 mt.toMethodDescriptorString(), null, null);
274 mv.visitAnnotation(DESCR_HIDDEN, true);
275 new ForwardingMethodGenerator(mv).generate(mt);
276 }
277 }
278
279 if (isSerializable)
288 final byte[] classBytes = cw.toByteArray();
289
290 // If requested, dump out to a file for debugging purposes
291 if (dumper != null) {
292 AccessController.doPrivileged(new PrivilegedAction<>() {
293 @Override
294 public Void run() {
295 dumper.dumpClass(lambdaClassName, classBytes);
296 return null;
297 }
298 }, null,
299 new FilePermission("<<ALL FILES>>", "read, write"),
300 // createDirectories may need it
301 new PropertyPermission("user.dir", "read"));
302 }
303
304 return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
305 }
306
307 /**
308 * Generate a static field that contains the singleton instance of the lambda
309 */
310 private void generateStaticField() {
311 String lambdaTypeDescriptor = BytecodeDescriptor.unparse(invokedType.returnType());
312
313 // Generate the static final field that holds the lambda singleton
314 FieldVisitor fv = cw.visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, LAMBDA_INSTANCE_FIELD, lambdaTypeDescriptor, null, null);
315 fv.visitEnd();
316
317 // Instantiate the lambda and store it to the static final field
318 MethodVisitor clinit = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
319 clinit.visitCode();
320
321 instantiateLambda(clinit);
322 clinit.visitFieldInsn(PUTSTATIC, lambdaClassName, LAMBDA_INSTANCE_FIELD, lambdaTypeDescriptor);
323
324 clinit.visitInsn(RETURN);
325 clinit.visitMaxs(-1, -1);
326 clinit.visitEnd();
327 }
328
329 /**
330 * Generate the factory method for the class
331 */
332 private void generateFactory() {
333 MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null);
334 m.visitCode();
335
336 instantiateLambda(m);
337 m.visitInsn(ARETURN);
338
339 m.visitMaxs(-1, -1);
340 m.visitEnd();
341 }
342
343 private void instantiateLambda(MethodVisitor m) {
344 m.visitTypeInsn(NEW, lambdaClassName);
345 m.visitInsn(Opcodes.DUP);
346 for (int typeIndex = 0, varIndex = 0; typeIndex < invokedType.parameterCount(); typeIndex++) {
347 Class<?> argType = invokedType.parameterType(typeIndex);
348 m.visitVarInsn(getLoadOpcode(argType), varIndex);
349 varIndex += getParameterSize(argType);
350 }
351 m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false);
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]);
|