> parameterTypes = resolveLambdaMethodParameterTypes(getType(object), functionalInterface);
+ if (parameterTypes.isEmpty() && object instanceof Serializable && isLambdaClass(getType(object))) {
+ parameterTypes = resolveSerializableLambdaParameterTypes((Serializable) object, functionalInterface);
+ }
+ return parameterTypes;
}
/**
@@ -167,6 +174,40 @@ static Class>[] resolveParameterTypes(Method actualMethod, Class>... declare
return matchedParameterTypes;
}
+ /**
+ * Resolve the parameter types of a serializable lambda using {@link SerializedLambda}.
+ *
+ * This method provides a reliable alternative to constant-pool inspection for lambda types
+ * that implement {@link Serializable}. It invokes the lambda's {@code writeReplace()} method
+ * to obtain a {@link SerializedLambda} descriptor containing the instantiated method type,
+ * from which the exact parameter types (including erased generic types) can be recovered.
+ *
+ *
+ * @param lambda the serializable lambda object
+ * @param functionalInterface the functional interface type
+ * @return the parameter types of the lambda method, or an empty list if they cannot be resolved
+ */
+ private static List> resolveSerializableLambdaParameterTypes(Serializable lambda, Class> functionalInterface) {
+ Method functionalInterfaceMethod = findFunctionalInterfaceMethod(functionalInterface);
+ if (functionalInterfaceMethod == null) {
+ return emptyList();
+ }
+ try {
+ Method writeReplace = lambda.getClass().getDeclaredMethod("writeReplace");
+ SerializedLambda sl = (SerializedLambda) writeReplace.invoke(lambda);
+ String instantiatedMethodType = sl.getInstantiatedMethodType();
+ ClassLoader classLoader = lambda.getClass().getClassLoader();
+ MethodType methodType = MethodType.fromMethodDescriptorString(instantiatedMethodType, classLoader);
+ List> parameterTypes = methodType.parameterList();
+ if (parameterTypes.size() == functionalInterfaceMethod.getParameterCount()) {
+ return parameterTypes;
+ }
+ } catch (Exception e) {
+ // silently ignore if SerializedLambda cannot be obtained
+ }
+ return emptyList();
+ }
+
private LambdaUtils() {
}
}
\ No newline at end of file