From f0e69e06b7c0b4b1c8cbf7c17cfc21ab92ce983c Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Fri, 23 Nov 2018 17:36:19 +0100 Subject: [PATCH] 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 (cherry-picked from commit 81fde5ec4103e3db28bf79073691938a4743b121) --- .../java/org/springframework/core/MethodParameter.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spring-core/src/main/java/org/springframework/core/MethodParameter.java b/spring-core/src/main/java/org/springframework/core/MethodParameter.java index a44ce5898a..d709fba357 100644 --- a/spring-core/src/main/java/org/springframework/core/MethodParameter.java +++ b/spring-core/src/main/java/org/springframework/core/MethodParameter.java @@ -725,11 +725,19 @@ public class MethodParameter { protected static int findParameterIndex(Parameter parameter) { Executable executable = parameter.getDeclaringExecutable(); Parameter[] allParams = executable.getParameters(); + // Try first with identity checks for greater performance. for (int i = 0; i < allParams.length; i++) { if (parameter == allParams[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 + "] does not match any parameter in the declaring executable"); }