Ensure that MethodParameter.findParameterIndex() is thread-safe

Prior to this commit, parallel invocations of
MethodParameter.findParameterIndex() (invoked indirectly via
SynthesizingMethodParameter.forParameter() and
MethodParameter.forParameter()) could intermittently lead to an
IllegalArgumentException being thrown due to a race condition in the
internal implementation of the JDK's
java.lang.reflect.Executable.getParameters() method.

This commit addresses this issue by introducing a fallback for-loop
that iterates over the candidate parameters a second time using
equality checks instead of identity checks.

Issue: SPR-17534
master
Sam Brannen 6 years ago
parent aa7f69a5d1
commit 81fde5ec41
  1. 8
      spring-core/src/main/java/org/springframework/core/MethodParameter.java

@ -733,11 +733,19 @@ public class MethodParameter {
protected static int findParameterIndex(Parameter parameter) { protected static int findParameterIndex(Parameter parameter) {
Executable executable = parameter.getDeclaringExecutable(); Executable executable = parameter.getDeclaringExecutable();
Parameter[] allParams = executable.getParameters(); Parameter[] allParams = executable.getParameters();
// Try first with identity checks for greater performance.
for (int i = 0; i < allParams.length; i++) { for (int i = 0; i < allParams.length; i++) {
if (parameter == allParams[i]) { if (parameter == allParams[i]) {
return i; return i;
} }
} }
// Potentially try again with object equality checks in order to avoid race
// conditions while invoking java.lang.reflect.Executable.getParameters().
for (int i = 0; i < allParams.length; i++) {
if (parameter.equals(allParams[i])) {
return i;
}
}
throw new IllegalArgumentException("Given parameter [" + parameter + throw new IllegalArgumentException("Given parameter [" + parameter +
"] does not match any parameter in the declaring executable"); "] does not match any parameter in the declaring executable");
} }

Loading…
Cancel
Save