23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package java.lang.invoke; |
26 package java.lang.invoke; |
27 |
27 |
28 import java.io.FileOutputStream; |
28 import java.lang.reflect.Constructor; |
29 import java.io.IOException; |
|
30 import java.lang.reflect.Method; |
29 import java.lang.reflect.Method; |
31 import java.security.ProtectionDomain; |
30 import java.security.ProtectionDomain; |
32 import java.util.concurrent.atomic.AtomicInteger; |
31 import java.util.concurrent.atomic.AtomicInteger; |
33 import sun.util.logging.PlatformLogger; |
|
34 import jdk.internal.org.objectweb.asm.*; |
32 import jdk.internal.org.objectweb.asm.*; |
35 import static jdk.internal.org.objectweb.asm.Opcodes.*; |
33 import static jdk.internal.org.objectweb.asm.Opcodes.*; |
36 import sun.misc.Unsafe; |
34 import sun.misc.Unsafe; |
|
35 import java.security.AccessController; |
|
36 import java.security.PrivilegedAction; |
37 |
37 |
38 /** |
38 /** |
39 * InnerClassLambdaMetafactory |
39 * InnerClassLambdaMetafactory |
40 */ |
40 */ |
41 /*non-public*/ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { |
41 /*non-public*/ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { |
118 * of the class which the CallSite will return, otherwise, generate handles |
118 * of the class which the CallSite will return, otherwise, generate handles |
119 * which will call the class' constructor. |
119 * which will call the class' constructor. |
120 * |
120 * |
121 * @return a CallSite, which, when invoked, will return an instance of the |
121 * @return a CallSite, which, when invoked, will return an instance of the |
122 * functional interface |
122 * functional interface |
123 * @throws ReflectiveOperationException |
123 * @throws ReflectiveOperationException, LambdaConversionException |
124 */ |
124 */ |
125 @Override |
125 @Override |
126 CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException { |
126 CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException { |
127 final Class<?> innerClass = spinInnerClass(); |
127 final Class<?> innerClass = spinInnerClass(); |
128 if (invokedType.parameterCount() == 0) { |
128 if (invokedType.parameterCount() == 0) { |
129 return new ConstantCallSite(MethodHandles.constant(samBase, innerClass.newInstance())); |
129 final Constructor[] ctrs = AccessController.doPrivileged( |
|
130 new PrivilegedAction<Constructor[]>() { |
|
131 @Override |
|
132 public Constructor[] run() { |
|
133 return innerClass.getDeclaredConstructors(); |
|
134 } |
|
135 }); |
|
136 if (ctrs.length != 1) { |
|
137 throw new ReflectiveOperationException("Expected one lambda constructor for " |
|
138 + innerClass.getCanonicalName() + ", got " + ctrs.length); |
|
139 } |
|
140 // The lambda implementing inner class constructor is private, set |
|
141 // it accessible (by us) before creating the constant sole instance |
|
142 AccessController.doPrivileged(new PrivilegedAction<Void>() { |
|
143 @Override |
|
144 public Void run() { |
|
145 ctrs[0].setAccessible(true); |
|
146 return null; |
|
147 } |
|
148 }); |
|
149 Object inst = ctrs[0].newInstance(); |
|
150 return new ConstantCallSite(MethodHandles.constant(samBase, inst)); |
130 } else { |
151 } else { |
131 return new ConstantCallSite( |
152 return new ConstantCallSite( |
132 MethodHandles.Lookup.IMPL_LOOKUP |
153 MethodHandles.Lookup.IMPL_LOOKUP |
133 .findConstructor(innerClass, constructorType) |
154 .findConstructor(innerClass, constructorType) |
134 .asType(constructorType.changeReturnType(samBase))); |
155 .asType(constructorType.changeReturnType(samBase))); |
142 * @return a Class which implements the functional interface |
163 * @return a Class which implements the functional interface |
143 */ |
164 */ |
144 private <T> Class<? extends T> spinInnerClass() throws LambdaConversionException { |
165 private <T> Class<? extends T> spinInnerClass() throws LambdaConversionException { |
145 String samName = samBase.getName().replace('.', '/'); |
166 String samName = samBase.getName().replace('.', '/'); |
146 |
167 |
147 cw.visit(CLASSFILE_VERSION, ACC_PUBLIC + ACC_SUPER, lambdaClassName, null, NAME_MAGIC_ACCESSOR_IMPL, |
168 cw.visit(CLASSFILE_VERSION, ACC_SUPER, lambdaClassName, null, NAME_MAGIC_ACCESSOR_IMPL, |
148 isSerializable ? new String[]{samName, NAME_SERIALIZABLE} : new String[]{samName}); |
169 isSerializable ? new String[]{samName, NAME_SERIALIZABLE} : new String[]{samName}); |
149 |
170 |
150 // Generate final fields to be filled in by constructor |
171 // Generate final fields to be filled in by constructor |
151 for (int i = 0; i < argTypes.length; i++) { |
172 for (int i = 0; i < argTypes.length; i++) { |
152 FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argTypes[i].getDescriptor(), null, null); |
173 FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argTypes[i].getDescriptor(), null, null); |
184 |
205 |
185 // Define the generated class in this VM. |
206 // Define the generated class in this VM. |
186 |
207 |
187 final byte[] classBytes = cw.toByteArray(); |
208 final byte[] classBytes = cw.toByteArray(); |
188 |
209 |
189 if (System.getProperty("debug.dump.generated") != null) { |
210 /*** Uncomment to dump the generated file |
190 System.out.printf("Loaded: %s (%d bytes) %n", lambdaClassName, classBytes.length); |
211 System.out.printf("Loaded: %s (%d bytes) %n", lambdaClassName, classBytes.length); |
191 try (FileOutputStream fos = new FileOutputStream(lambdaClassName.replace('/', '.') + ".class")) { |
212 try (FileOutputStream fos = new FileOutputStream(lambdaClassName.replace('/', '.') + ".class")) { |
192 fos.write(classBytes); |
213 fos.write(classBytes); |
193 } catch (IOException ex) { |
214 } catch (IOException ex) { |
194 PlatformLogger.getLogger(InnerClassLambdaMetafactory.class.getName()).severe(ex.getMessage(), ex); |
215 Logger.getLogger(InnerClassLambdaMetafactory.class.getName()).log(Level.SEVERE, null, ex); |
195 } |
216 } |
196 } |
217 ***/ |
197 |
218 |
198 ClassLoader loader = targetClass.getClassLoader(); |
219 ClassLoader loader = targetClass.getClassLoader(); |
199 ProtectionDomain pd = (loader == null) ? null : targetClass.getProtectionDomain(); |
220 ProtectionDomain pd = (loader == null) |
|
221 ? null |
|
222 : AccessController.doPrivileged( |
|
223 new PrivilegedAction<ProtectionDomain>() { |
|
224 @Override |
|
225 public ProtectionDomain run() { |
|
226 return targetClass.getProtectionDomain(); |
|
227 } |
|
228 } |
|
229 ); |
|
230 |
200 return (Class<? extends T>) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length, loader, pd); |
231 return (Class<? extends T>) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length, loader, pd); |
201 } |
232 } |
202 |
233 |
203 /** |
234 /** |
204 * Generate the constructor for the class |
235 * Generate the constructor for the class |
205 */ |
236 */ |
206 private void generateConstructor() { |
237 private void generateConstructor() { |
207 // Generate constructor |
238 // Generate constructor |
208 MethodVisitor ctor = cw.visitMethod(ACC_PUBLIC, NAME_CTOR, constructorDesc, null, null); |
239 MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, constructorDesc, null, null); |
209 ctor.visitCode(); |
240 ctor.visitCode(); |
210 ctor.visitVarInsn(ALOAD, 0); |
241 ctor.visitVarInsn(ALOAD, 0); |
211 ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR, METHOD_DESCRIPTOR_VOID); |
242 ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR, METHOD_DESCRIPTOR_VOID); |
212 int lvIndex = 0; |
243 int lvIndex = 0; |
213 for (int i = 0; i < argTypes.length; i++) { |
244 for (int i = 0; i < argTypes.length; i++) { |