4
4
import org .junit .Test ;
5
5
6
6
import java .io .Serializable ;
7
- import java .lang .invoke .MethodHandle ;
8
- import java .lang .invoke .MethodHandles ;
9
- import java .lang .invoke .SerializedLambda ;
7
+ import java .lang .invoke .*;
10
8
import java .lang .reflect .Method ;
11
9
import java .util .Arrays ;
12
10
import java .util .HashMap ;
@@ -85,19 +83,20 @@ public void cachedStatic() {
85
83
public void implMethodNameChanged () {
86
84
F1 <Boolean , String > f1 = lambdaHost .lambdaBackedByStaticImplMethod ();
87
85
SerializedLambda sl = writeReplace (f1 );
88
- checkIllegalAccess (copySerializedLambda (sl , sl .getImplMethodName () + "___" , sl .getImplMethodSignature ()));
86
+ checkIllegalAccess (sl , copySerializedLambda (sl , sl .getImplMethodName () + "___" , sl .getImplMethodSignature ()));
89
87
}
90
88
91
89
@ Test
92
90
public void implMethodSignatureChanged () {
93
91
F1 <Boolean , String > f1 = lambdaHost .lambdaBackedByStaticImplMethod ();
94
92
SerializedLambda sl = writeReplace (f1 );
95
- checkIllegalAccess (copySerializedLambda (sl , sl .getImplMethodName (), sl .getImplMethodSignature ().replace ("Boolean" , "Integer" )));
93
+ checkIllegalAccess (sl , copySerializedLambda (sl , sl .getImplMethodName (), sl .getImplMethodSignature ().replace ("Boolean" , "Integer" )));
96
94
}
97
95
98
- private void checkIllegalAccess (SerializedLambda serialized ) {
96
+ private void checkIllegalAccess (SerializedLambda allowed , SerializedLambda requested ) {
99
97
try {
100
- LambdaDeserializer .deserializeLambda (MethodHandles .lookup (), null , null , serialized );
98
+ HashMap <String , MethodHandle > allowedMap = createAllowedMap (LambdaHost .lookup (), allowed );
99
+ LambdaDeserializer .deserializeLambda (MethodHandles .lookup (), null , allowedMap , requested );
101
100
throw new AssertionError ();
102
101
} catch (IllegalArgumentException iae ) {
103
102
if (!iae .getMessage ().contains ("Illegal lambda deserialization" )) {
@@ -123,19 +122,64 @@ private Class<?> loadClass(String className) {
123
122
throw new RuntimeException (e );
124
123
}
125
124
}
125
+
126
126
private <A , B > A reconstitute (A f1 ) {
127
127
return reconstitute (f1 , null );
128
128
}
129
129
130
130
@ SuppressWarnings ("unchecked" )
131
131
private <A , B > A reconstitute (A f1 , java .util .HashMap <String , MethodHandle > cache ) {
132
132
try {
133
- return ( A ) LambdaDeserializer . deserializeLambda ( LambdaHost . lookup () , cache , null , writeReplace ( f1 ));
133
+ return deserizalizeLambdaCreatingAllowedMap ( f1 , cache , LambdaHost . lookup ( ));
134
134
} catch (Exception e ) {
135
135
throw new RuntimeException (e );
136
136
}
137
137
}
138
138
139
+ private <A > A deserizalizeLambdaCreatingAllowedMap (A f1 , HashMap <String , MethodHandle > cache , MethodHandles .Lookup lookup ) {
140
+ SerializedLambda serialized = writeReplace (f1 );
141
+ HashMap <String , MethodHandle > allowed = createAllowedMap (lookup , serialized );
142
+ return (A ) LambdaDeserializer .deserializeLambda (lookup , cache , allowed , serialized );
143
+ }
144
+
145
+ private HashMap <String , MethodHandle > createAllowedMap (MethodHandles .Lookup lookup , SerializedLambda serialized ) {
146
+ Class <?> implClass = classForName (serialized .getImplClass ().replace ("/" , "." ), lookup .lookupClass ().getClassLoader ());
147
+ MethodHandle implMethod = findMember (lookup , serialized .getImplMethodKind (), implClass , serialized .getImplMethodName (), MethodType .fromMethodDescriptorString (serialized .getImplMethodSignature (), lookup .lookupClass ().getClassLoader ()));
148
+ HashMap <String , MethodHandle > allowed = new HashMap <>();
149
+ allowed .put (LambdaDeserialize .nameAndDescriptorKey (serialized .getImplMethodName (), serialized .getImplMethodSignature ()), implMethod );
150
+ return allowed ;
151
+ }
152
+
153
+ private Class <?> classForName (String className , ClassLoader classLoader ) {
154
+ try {
155
+ return Class .forName (className , true , classLoader );
156
+ } catch (ClassNotFoundException e ) {
157
+ throw new RuntimeException (e );
158
+ }
159
+ }
160
+
161
+ private MethodHandle findMember (MethodHandles .Lookup lookup , int kind , Class <?> owner ,
162
+ String name , MethodType signature ) {
163
+ try {
164
+ switch (kind ) {
165
+ case MethodHandleInfo .REF_invokeStatic :
166
+ return lookup .findStatic (owner , name , signature );
167
+ case MethodHandleInfo .REF_newInvokeSpecial :
168
+ return lookup .findConstructor (owner , signature );
169
+ case MethodHandleInfo .REF_invokeVirtual :
170
+ case MethodHandleInfo .REF_invokeInterface :
171
+ return lookup .findVirtual (owner , name , signature );
172
+ case MethodHandleInfo .REF_invokeSpecial :
173
+ return lookup .findSpecial (owner , name , signature , owner );
174
+ default :
175
+ throw new IllegalArgumentException ();
176
+ }
177
+ } catch (NoSuchMethodException | IllegalAccessException e ) {
178
+ throw new RuntimeException (e );
179
+ }
180
+ }
181
+
182
+
139
183
private <A > SerializedLambda writeReplace (A f1 ) {
140
184
try {
141
185
Method writeReplace = f1 .getClass ().getDeclaredMethod ("writeReplace" );
@@ -189,5 +233,7 @@ public static MethodHandles.Lookup lookup() {
189
233
}
190
234
191
235
interface I {
192
- default String i () { return "i" ; };
236
+ default String i () {
237
+ return "i" ;
238
+ }
193
239
}
0 commit comments