author | henryjen |
Wed, 09 Oct 2013 09:41:40 -0700 | |
changeset 20748 | fbf53402134d |
parent 18716 | 9723e722b955 |
child 21300 | 9a71d04b2d02 |
permissions | -rw-r--r-- |
14323 | 1 |
/* |
2 |
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. |
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
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 |
||
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
28 |
import jdk.internal.org.objectweb.asm.*; |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
29 |
import sun.misc.Unsafe; |
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
30 |
import sun.security.action.GetPropertyAction; |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
31 |
|
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
32 |
import java.io.FilePermission; |
18284 | 33 |
import java.lang.reflect.Constructor; |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
34 |
import java.security.AccessController; |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
35 |
import java.security.PrivilegedAction; |
18284 | 36 |
import java.security.ProtectionDomain; |
37 |
import java.util.concurrent.atomic.AtomicInteger; |
|
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
38 |
import java.util.PropertyPermission; |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
39 |
|
18284 | 40 |
import static jdk.internal.org.objectweb.asm.Opcodes.*; |
14323 | 41 |
|
42 |
/** |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
43 |
* Lambda metafactory implementation which dynamically creates an |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
44 |
* inner-class-like class per lambda callsite. |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
45 |
* |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
46 |
* @see LambdaMetafactory |
14323 | 47 |
*/ |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
48 |
/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
49 |
private static final Unsafe UNSAFE = Unsafe.getUnsafe(); |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
50 |
|
14323 | 51 |
private static final int CLASSFILE_VERSION = 51; |
52 |
private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE); |
|
53 |
private static final String NAME_MAGIC_ACCESSOR_IMPL = "java/lang/invoke/MagicLambdaImpl"; |
|
54 |
private static final String NAME_CTOR = "<init>"; |
|
55 |
||
56 |
//Serialization support |
|
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
57 |
private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda"; |
14323 | 58 |
private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;"; |
59 |
private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace"; |
|
60 |
private static final String NAME_OBJECT = "java/lang/Object"; |
|
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
61 |
private static final String DESCR_CTOR_SERIALIZED_LAMBDA |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
62 |
= MethodType.methodType(void.class, |
16034
cb5fbea1ecec
8008770: SerializedLambda incorrect class loader for lambda deserializing class
rfield
parents:
16001
diff
changeset
|
63 |
Class.class, |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
64 |
String.class, String.class, String.class, |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
65 |
int.class, String.class, String.class, String.class, |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
66 |
String.class, |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
67 |
Object[].class).toMethodDescriptorString(); |
14323 | 68 |
|
69 |
// Used to ensure that each spun class name is unique |
|
70 |
private static final AtomicInteger counter = new AtomicInteger(0); |
|
71 |
||
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
72 |
// For dumping generated classes to disk, for debugging purposes |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
73 |
private static final ProxyClassesDumper dumper; |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
74 |
|
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
75 |
static { |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
76 |
final String key = "jdk.internal.lambda.dumpProxyClasses"; |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
77 |
String path = AccessController.doPrivileged( |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
78 |
new GetPropertyAction(key), null, |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
79 |
new PropertyPermission(key , "read")); |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
80 |
dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path); |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
81 |
} |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
82 |
|
14323 | 83 |
// See context values in AbstractValidatingLambdaMetafactory |
84 |
private final String implMethodClassName; // Name of type containing implementation "CC" |
|
85 |
private final String implMethodName; // Name of implementation method "impl" |
|
86 |
private final String implMethodDesc; // Type descriptor for implementation methods "(I)Ljava/lang/String;" |
|
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
87 |
private final Type[] implMethodArgumentTypes; // ASM types for implementation method parameters |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
88 |
private final Type implMethodReturnType; // ASM type for implementation method return type "Ljava/lang/String;" |
14323 | 89 |
private final MethodType constructorType; // Generated class constructor type "(CC)void" |
90 |
private final String constructorDesc; // Type descriptor for constructor "(LCC;)V" |
|
91 |
private final ClassWriter cw; // ASM class writer |
|
92 |
private final Type[] argTypes; // ASM types for the constructor arguments |
|
93 |
private final String[] argNames; // Generated names for the constructor arguments |
|
94 |
private final String lambdaClassName; // Generated name for the generated class "X$$Lambda$1" |
|
95 |
private final Type[] instantiatedArgumentTypes; // ASM types for the functional interface arguments |
|
96 |
||
97 |
/** |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
98 |
* General meta-factory constructor, supporting both standard cases and |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
99 |
* allowing for uncommon options such as serialization or bridging. |
14323 | 100 |
* |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
101 |
* @param caller Stacked automatically by VM; represents a lookup context |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
102 |
* with the accessibility privileges of the caller. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
103 |
* @param invokedType Stacked automatically by VM; the signature of the |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
104 |
* invoked method, which includes the expected static |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
105 |
* type of the returned lambda object, and the static |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
106 |
* types of the captured arguments for the lambda. In |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
107 |
* the event that the implementation method is an |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
108 |
* instance method, the first argument in the invocation |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
109 |
* signature will correspond to the receiver. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
110 |
* @param samMethodName Name of the method in the functional interface to |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
111 |
* which the lambda or method reference is being |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
112 |
* converted, represented as a String. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
113 |
* @param samMethodType Type of the method in the functional interface to |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
114 |
* which the lambda or method reference is being |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
115 |
* converted, represented as a MethodType. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
116 |
* @param implMethod The implementation method which should be called (with |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
117 |
* suitable adaptation of argument types, return types, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
118 |
* and adjustment for captured arguments) when methods of |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
119 |
* the resulting functional interface instance are invoked. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
120 |
* @param instantiatedMethodType The signature of the primary functional |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
121 |
* interface method after type variables are |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
122 |
* substituted with their instantiation from |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
123 |
* the capture site |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
124 |
* @param isSerializable Should the lambda be made serializable? If set, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
125 |
* either the target type or one of the additional SAM |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
126 |
* types must extend {@code Serializable}. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
127 |
* @param markerInterfaces Additional interfaces which the lambda object |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
128 |
* should implement. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
129 |
* @param additionalBridges Method types for additional signatures to be |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
130 |
* bridged to the implementation method |
14323 | 131 |
* @throws ReflectiveOperationException |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
132 |
* @throws LambdaConversionException If any of the meta-factory protocol |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
133 |
* invariants are violated |
14323 | 134 |
*/ |
135 |
public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, |
|
136 |
MethodType invokedType, |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
137 |
String samMethodName, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
138 |
MethodType samMethodType, |
14323 | 139 |
MethodHandle implMethod, |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
140 |
MethodType instantiatedMethodType, |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
141 |
boolean isSerializable, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
142 |
Class<?>[] markerInterfaces, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
143 |
MethodType[] additionalBridges) |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
144 |
throws ReflectiveOperationException, LambdaConversionException { |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
145 |
super(caller, invokedType, samMethodName, samMethodType, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
146 |
implMethod, instantiatedMethodType, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
147 |
isSerializable, markerInterfaces, additionalBridges); |
14323 | 148 |
implMethodClassName = implDefiningClass.getName().replace('.', '/'); |
149 |
implMethodName = implInfo.getName(); |
|
150 |
implMethodDesc = implMethodType.toMethodDescriptorString(); |
|
151 |
Type implMethodAsmType = Type.getMethodType(implMethodDesc); |
|
152 |
implMethodArgumentTypes = implMethodAsmType.getArgumentTypes(); |
|
18556
0fe397a41c18
8016761: Lambda metafactory - incorrect type conversion of constructor method handle
rfield
parents:
18284
diff
changeset
|
153 |
implMethodReturnType = (implKind == MethodHandleInfo.REF_newInvokeSpecial) |
0fe397a41c18
8016761: Lambda metafactory - incorrect type conversion of constructor method handle
rfield
parents:
18284
diff
changeset
|
154 |
? Type.getObjectType(implMethodClassName) |
0fe397a41c18
8016761: Lambda metafactory - incorrect type conversion of constructor method handle
rfield
parents:
18284
diff
changeset
|
155 |
: implMethodAsmType.getReturnType(); |
14323 | 156 |
constructorType = invokedType.changeReturnType(Void.TYPE); |
157 |
constructorDesc = constructorType.toMethodDescriptorString(); |
|
158 |
lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet(); |
|
159 |
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); |
|
160 |
argTypes = Type.getArgumentTypes(constructorDesc); |
|
161 |
argNames = new String[argTypes.length]; |
|
162 |
for (int i = 0; i < argTypes.length; i++) { |
|
163 |
argNames[i] = "arg$" + (i + 1); |
|
164 |
} |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
165 |
instantiatedArgumentTypes = Type.getArgumentTypes( |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
166 |
instantiatedMethodType.toMethodDescriptorString()); |
14323 | 167 |
} |
168 |
||
169 |
/** |
|
170 |
* Build the CallSite. Generate a class file which implements the functional |
|
171 |
* interface, define the class, if there are no parameters create an instance |
|
172 |
* of the class which the CallSite will return, otherwise, generate handles |
|
173 |
* which will call the class' constructor. |
|
174 |
* |
|
175 |
* @return a CallSite, which, when invoked, will return an instance of the |
|
176 |
* functional interface |
|
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
177 |
* @throws ReflectiveOperationException |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
178 |
* @throws LambdaConversionException If properly formed functional interface |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
179 |
* is not found |
14323 | 180 |
*/ |
181 |
@Override |
|
182 |
CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException { |
|
183 |
final Class<?> innerClass = spinInnerClass(); |
|
184 |
if (invokedType.parameterCount() == 0) { |
|
14762
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
185 |
final Constructor[] ctrs = AccessController.doPrivileged( |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
186 |
new PrivilegedAction<Constructor[]>() { |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
187 |
@Override |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
188 |
public Constructor[] run() { |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
189 |
return innerClass.getDeclaredConstructors(); |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
190 |
} |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
191 |
}); |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
192 |
if (ctrs.length != 1) { |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
193 |
throw new ReflectiveOperationException("Expected one lambda constructor for " |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
194 |
+ innerClass.getCanonicalName() + ", got " + ctrs.length); |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
195 |
} |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
196 |
// The lambda implementing inner class constructor is private, set |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
197 |
// it accessible (by us) before creating the constant sole instance |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
198 |
AccessController.doPrivileged(new PrivilegedAction<Void>() { |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
199 |
@Override |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
200 |
public Void run() { |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
201 |
ctrs[0].setAccessible(true); |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
202 |
return null; |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
203 |
} |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
204 |
}); |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
205 |
Object inst = ctrs[0].newInstance(); |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
206 |
return new ConstantCallSite(MethodHandles.constant(samBase, inst)); |
14323 | 207 |
} else { |
208 |
return new ConstantCallSite( |
|
209 |
MethodHandles.Lookup.IMPL_LOOKUP |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
210 |
.findConstructor(innerClass, constructorType) |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
211 |
.asType(constructorType.changeReturnType(samBase))); |
14323 | 212 |
} |
213 |
} |
|
214 |
||
215 |
/** |
|
216 |
* Generate a class file which implements the functional |
|
217 |
* interface, define and return the class. |
|
218 |
* |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
219 |
* @implNote The class that is generated does not include signature |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
220 |
* information for exceptions that may be present on the SAM method. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
221 |
* This is to reduce classfile size, and is harmless as checked exceptions |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
222 |
* are erased anyway, no one will ever compile against this classfile, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
223 |
* and we make no guarantees about the reflective properties of lambda |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
224 |
* objects. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
225 |
* |
14323 | 226 |
* @return a Class which implements the functional interface |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
227 |
* @throws LambdaConversionException If properly formed functional interface |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
228 |
* is not found |
14323 | 229 |
*/ |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
230 |
private Class<?> spinInnerClass() throws LambdaConversionException { |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
231 |
String[] interfaces = new String[markerInterfaces.length + 1]; |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
232 |
interfaces[0] = samBase.getName().replace('.', '/'); |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
233 |
for (int i=0; i<markerInterfaces.length; i++) { |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
234 |
interfaces[i+1] = markerInterfaces[i].getName().replace('.', '/'); |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
235 |
} |
16859
45fbee947921
8012028: Metafactory-generated lambda classes should be final
rfield
parents:
16854
diff
changeset
|
236 |
cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC, |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
237 |
lambdaClassName, null, |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
238 |
NAME_MAGIC_ACCESSOR_IMPL, interfaces); |
14323 | 239 |
|
240 |
// Generate final fields to be filled in by constructor |
|
241 |
for (int i = 0; i < argTypes.length; i++) { |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
242 |
FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
243 |
argNames[i], |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
244 |
argTypes[i].getDescriptor(), |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
245 |
null, null); |
14323 | 246 |
fv.visitEnd(); |
247 |
} |
|
248 |
||
249 |
generateConstructor(); |
|
250 |
||
251 |
// Forward the SAM method |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
252 |
String methodDescriptor = samMethodType.toMethodDescriptorString(); |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
253 |
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
254 |
methodDescriptor, null, null); |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
255 |
new ForwardingMethodGenerator(mv).generate(methodDescriptor); |
14323 | 256 |
|
257 |
// Forward the bridges |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
258 |
if (additionalBridges != null) { |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
259 |
for (MethodType mt : additionalBridges) { |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
260 |
methodDescriptor = mt.toMethodDescriptorString(); |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
261 |
mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
262 |
methodDescriptor, null, null); |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
263 |
new ForwardingMethodGenerator(mv).generate(methodDescriptor); |
14323 | 264 |
} |
265 |
} |
|
266 |
||
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
267 |
if (isSerializable) |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
268 |
generateWriteReplace(); |
14323 | 269 |
|
270 |
cw.visitEnd(); |
|
271 |
||
272 |
// Define the generated class in this VM. |
|
273 |
||
274 |
final byte[] classBytes = cw.toByteArray(); |
|
275 |
||
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
276 |
// If requested, dump out to a file for debugging purposes |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
277 |
if (dumper != null) { |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
278 |
AccessController.doPrivileged(new PrivilegedAction<Void>() { |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
279 |
@Override |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
280 |
public Void run() { |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
281 |
dumper.dumpClass(lambdaClassName, classBytes); |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
282 |
return null; |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
283 |
} |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
284 |
}, null, |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
285 |
new FilePermission("<<ALL FILES>>", "read, write"), |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
286 |
// createDirectories may need it |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
287 |
new PropertyPermission("user.dir", "read")); |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
288 |
} |
14323 | 289 |
|
290 |
ClassLoader loader = targetClass.getClassLoader(); |
|
14762
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
291 |
ProtectionDomain pd = (loader == null) |
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
292 |
? null |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
293 |
: AccessController.doPrivileged( |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
294 |
new PrivilegedAction<ProtectionDomain>() { |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
295 |
@Override |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
296 |
public ProtectionDomain run() { |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
297 |
return targetClass.getProtectionDomain(); |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
298 |
} |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
299 |
} |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
300 |
); |
14762
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
301 |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
302 |
return UNSAFE.defineClass(lambdaClassName, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
303 |
classBytes, 0, classBytes.length, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
304 |
loader, pd); |
14323 | 305 |
} |
306 |
||
307 |
/** |
|
308 |
* Generate the constructor for the class |
|
309 |
*/ |
|
310 |
private void generateConstructor() { |
|
311 |
// Generate constructor |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
312 |
MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
313 |
constructorDesc, null, null); |
14323 | 314 |
ctor.visitCode(); |
315 |
ctor.visitVarInsn(ALOAD, 0); |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
316 |
ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
317 |
METHOD_DESCRIPTOR_VOID); |
14323 | 318 |
int lvIndex = 0; |
319 |
for (int i = 0; i < argTypes.length; i++) { |
|
320 |
ctor.visitVarInsn(ALOAD, 0); |
|
321 |
ctor.visitVarInsn(argTypes[i].getOpcode(ILOAD), lvIndex + 1); |
|
322 |
lvIndex += argTypes[i].getSize(); |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
323 |
ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
324 |
argTypes[i].getDescriptor()); |
14323 | 325 |
} |
326 |
ctor.visitInsn(RETURN); |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
327 |
// Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
328 |
ctor.visitMaxs(-1, -1); |
14323 | 329 |
ctor.visitEnd(); |
330 |
} |
|
331 |
||
332 |
/** |
|
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
333 |
* Generate the writeReplace method (if needed for serialization) |
14323 | 334 |
*/ |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
335 |
private void generateWriteReplace() { |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
336 |
TypeConvertingMethodAdapter mv |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
337 |
= new TypeConvertingMethodAdapter( |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
338 |
cw.visitMethod(ACC_PRIVATE + ACC_FINAL, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
339 |
NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
340 |
null, null)); |
14323 | 341 |
|
342 |
mv.visitCode(); |
|
343 |
mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA); |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
344 |
mv.visitInsn(DUP); |
16034
cb5fbea1ecec
8008770: SerializedLambda incorrect class loader for lambda deserializing class
rfield
parents:
16001
diff
changeset
|
345 |
mv.visitLdcInsn(Type.getType(targetClass)); |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
346 |
mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/')); |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
347 |
mv.visitLdcInsn(samMethodName); |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
348 |
mv.visitLdcInsn(samMethodType.toMethodDescriptorString()); |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
349 |
mv.visitLdcInsn(implInfo.getReferenceKind()); |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
350 |
mv.visitLdcInsn(implInfo.getDeclaringClass().getName().replace('.', '/')); |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
351 |
mv.visitLdcInsn(implInfo.getName()); |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
352 |
mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString()); |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
353 |
mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString()); |
14323 | 354 |
|
355 |
mv.iconst(argTypes.length); |
|
356 |
mv.visitTypeInsn(ANEWARRAY, NAME_OBJECT); |
|
357 |
for (int i = 0; i < argTypes.length; i++) { |
|
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
358 |
mv.visitInsn(DUP); |
14323 | 359 |
mv.iconst(i); |
360 |
mv.visitVarInsn(ALOAD, 0); |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
361 |
mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
362 |
argTypes[i].getDescriptor()); |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
363 |
mv.boxIfTypePrimitive(argTypes[i]); |
14323 | 364 |
mv.visitInsn(AASTORE); |
365 |
} |
|
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
366 |
mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR, |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
367 |
DESCR_CTOR_SERIALIZED_LAMBDA); |
14323 | 368 |
mv.visitInsn(ARETURN); |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
369 |
// Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
370 |
mv.visitMaxs(-1, -1); |
14323 | 371 |
mv.visitEnd(); |
372 |
} |
|
373 |
||
374 |
/** |
|
375 |
* This class generates a method body which calls the lambda implementation |
|
376 |
* method, converting arguments, as needed. |
|
377 |
*/ |
|
378 |
private class ForwardingMethodGenerator extends TypeConvertingMethodAdapter { |
|
379 |
||
380 |
ForwardingMethodGenerator(MethodVisitor mv) { |
|
381 |
super(mv); |
|
382 |
} |
|
383 |
||
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
384 |
void generate(String methodDescriptor) { |
14323 | 385 |
visitCode(); |
386 |
||
387 |
if (implKind == MethodHandleInfo.REF_newInvokeSpecial) { |
|
388 |
visitTypeInsn(NEW, implMethodClassName); |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
389 |
visitInsn(DUP); |
14323 | 390 |
} |
391 |
for (int i = 0; i < argTypes.length; i++) { |
|
392 |
visitVarInsn(ALOAD, 0); |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
393 |
visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
394 |
argTypes[i].getDescriptor()); |
14323 | 395 |
} |
396 |
||
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
397 |
convertArgumentTypes(Type.getArgumentTypes(methodDescriptor)); |
14323 | 398 |
|
399 |
// Invoke the method we want to forward to |
|
400 |
visitMethodInsn(invocationOpcode(), implMethodClassName, implMethodName, implMethodDesc); |
|
401 |
||
402 |
// Convert the return value (if any) and return it |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
403 |
// Note: if adapting from non-void to void, the 'return' |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
404 |
// instruction will pop the unneeded result |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
405 |
Type samReturnType = Type.getReturnType(methodDescriptor); |
14323 | 406 |
convertType(implMethodReturnType, samReturnType, samReturnType); |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
407 |
visitInsn(samReturnType.getOpcode(Opcodes.IRETURN)); |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
408 |
// Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
409 |
visitMaxs(-1, -1); |
14323 | 410 |
visitEnd(); |
411 |
} |
|
412 |
||
413 |
private void convertArgumentTypes(Type[] samArgumentTypes) { |
|
414 |
int lvIndex = 0; |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
415 |
boolean samIncludesReceiver = implIsInstanceMethod && |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
416 |
argTypes.length == 0; |
14323 | 417 |
int samReceiverLength = samIncludesReceiver ? 1 : 0; |
418 |
if (samIncludesReceiver) { |
|
419 |
// push receiver |
|
420 |
Type rcvrType = samArgumentTypes[0]; |
|
421 |
Type instantiatedRcvrType = instantiatedArgumentTypes[0]; |
|
422 |
||
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
423 |
visitVarInsn(rcvrType.getOpcode(ILOAD), lvIndex + 1); |
14323 | 424 |
lvIndex += rcvrType.getSize(); |
425 |
convertType(rcvrType, Type.getType(implDefiningClass), instantiatedRcvrType); |
|
426 |
} |
|
427 |
int argOffset = implMethodArgumentTypes.length - samArgumentTypes.length; |
|
428 |
for (int i = samReceiverLength; i < samArgumentTypes.length; i++) { |
|
429 |
Type argType = samArgumentTypes[i]; |
|
430 |
Type targetType = implMethodArgumentTypes[argOffset + i]; |
|
431 |
Type instantiatedArgType = instantiatedArgumentTypes[i]; |
|
432 |
||
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
433 |
visitVarInsn(argType.getOpcode(ILOAD), lvIndex + 1); |
14323 | 434 |
lvIndex += argType.getSize(); |
435 |
convertType(argType, targetType, instantiatedArgType); |
|
436 |
} |
|
437 |
} |
|
438 |
||
439 |
private void convertType(Type argType, Type targetType, Type functionalType) { |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
440 |
convertType(argType.getDescriptor(), |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
441 |
targetType.getDescriptor(), |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
442 |
functionalType.getDescriptor()); |
14323 | 443 |
} |
444 |
||
445 |
private int invocationOpcode() throws InternalError { |
|
446 |
switch (implKind) { |
|
447 |
case MethodHandleInfo.REF_invokeStatic: |
|
448 |
return INVOKESTATIC; |
|
449 |
case MethodHandleInfo.REF_newInvokeSpecial: |
|
450 |
return INVOKESPECIAL; |
|
451 |
case MethodHandleInfo.REF_invokeVirtual: |
|
452 |
return INVOKEVIRTUAL; |
|
453 |
case MethodHandleInfo.REF_invokeInterface: |
|
454 |
return INVOKEINTERFACE; |
|
455 |
case MethodHandleInfo.REF_invokeSpecial: |
|
456 |
return INVOKESPECIAL; |
|
457 |
default: |
|
458 |
throw new InternalError("Unexpected invocation kind: " + implKind); |
|
459 |
} |
|
460 |
} |
|
461 |
} |
|
462 |
} |