Skip to content

Commit c79e4e2

Browse files
committed
Reinstantiate checks for kotlin-reflect
This commit reinstantiates checks for kotlin-reflect (via static final fields for faster Java code paths and better native code removal) which were removed as part of gh-34275, which did not consider the increasingly popular use cases where kotlin-stdlib is present in the classpath as a transitive dependency in Java applications. Closes gh-35511
1 parent 7635ac3 commit c79e4e2

File tree

12 files changed

+56
-21
lines changed

12 files changed

+56
-21
lines changed

spring-beans/src/main/java/org/springframework/beans/BeanUtils.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ public abstract class BeanUtils {
8888
double.class, 0D,
8989
char.class, '\0');
9090

91+
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
92+
9193

9294
/**
9395
* Convenience method to instantiate a class using its no-arg constructor.
@@ -186,7 +188,7 @@ public static <T> T instantiateClass(Constructor<T> ctor, @Nullable Object... ar
186188
Assert.notNull(ctor, "Constructor must not be null");
187189
try {
188190
ReflectionUtils.makeAccessible(ctor);
189-
if (KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
191+
if (KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
190192
return KotlinDelegate.instantiateClass(ctor, args);
191193
}
192194
else {
@@ -279,7 +281,7 @@ else if (ctors.length == 0) {
279281
*/
280282
public static <T> @Nullable Constructor<T> findPrimaryConstructor(Class<T> clazz) {
281283
Assert.notNull(clazz, "Class must not be null");
282-
if (KotlinDetector.isKotlinType(clazz)) {
284+
if (KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(clazz)) {
283285
return KotlinDelegate.findPrimaryConstructor(clazz);
284286
}
285287
if (clazz.isRecord()) {
@@ -659,7 +661,7 @@ public static MethodParameter getWriteMethodParameter(PropertyDescriptor pd) {
659661
ConstructorProperties cp = ctor.getAnnotation(ConstructorProperties.class);
660662
@Nullable String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor));
661663
Assert.state(paramNames != null, () -> "Cannot resolve parameter names for constructor " + ctor);
662-
int parameterCount = (KotlinDetector.isKotlinReflectPresent() && KotlinDelegate.hasDefaultConstructorMarker(ctor) ?
664+
int parameterCount = (KOTLIN_REFLECT_PRESENT && KotlinDelegate.hasDefaultConstructorMarker(ctor) ?
663665
ctor.getParameterCount() - 1 : ctor.getParameterCount());
664666
Assert.state(paramNames.length == parameterCount,
665667
() -> "Invalid number of parameter names: " + paramNames.length + " for constructor " + ctor);

spring-beans/src/main/java/org/springframework/beans/factory/aot/InstanceSupplierCodeGenerator.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ public class InstanceSupplierCodeGenerator {
8888

8989
private static final CodeBlock NO_ARGS = CodeBlock.of("");
9090

91+
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
92+
9193

9294
private final GenerationContext generationContext;
9395

@@ -161,7 +163,7 @@ private CodeBlock generateCodeForConstructor(RegisteredBean registeredBean, Cons
161163
registeredBean.getBeanName(), constructor, registeredBean.getBeanClass());
162164

163165
Class<?> publicType = descriptor.publicType();
164-
if (KotlinDetector.isKotlinType(publicType) && KotlinDelegate.hasConstructorWithOptionalParameter(publicType)) {
166+
if (KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(publicType) && KotlinDelegate.hasConstructorWithOptionalParameter(publicType)) {
165167
return generateCodeForInaccessibleConstructor(descriptor,
166168
hints -> hints.registerType(publicType, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS));
167169
}

spring-core/src/main/java/org/springframework/core/DefaultParameterNameDiscoverer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@
3535
*/
3636
public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDiscoverer {
3737

38+
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
39+
40+
3841
public DefaultParameterNameDiscoverer() {
39-
if (KotlinDetector.isKotlinReflectPresent()) {
42+
if (KOTLIN_REFLECT_PRESENT) {
4043
addDiscoverer(new KotlinReflectionParameterNameDiscoverer());
4144
}
4245

spring-core/src/main/java/org/springframework/core/MethodParameter.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public class MethodParameter {
6666

6767
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
6868

69+
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
70+
6971

7072
private final Executable executable;
7173

@@ -396,7 +398,8 @@ private MethodParameter nested(int nestingLevel, @Nullable Integer typeIndex) {
396398
*/
397399
public boolean isOptional() {
398400
return (getParameterType() == Optional.class || Nullness.forMethodParameter(this) == Nullness.NULLABLE ||
399-
(KotlinDetector.isKotlinType(getContainingClass()) && KotlinDelegate.isOptional(this)));
401+
(KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(getContainingClass()) &&
402+
KotlinDelegate.isOptional(this)));
400403
}
401404

402405
/**
@@ -484,7 +487,7 @@ public Type getGenericParameterType() {
484487
if (this.parameterIndex < 0) {
485488
Method method = getMethod();
486489
paramType = (method != null ?
487-
(KotlinDetector.isKotlinType(getContainingClass()) ?
490+
(KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(getContainingClass()) ?
488491
KotlinDelegate.getGenericReturnType(method) : method.getGenericReturnType()) : void.class);
489492
}
490493
else {
@@ -512,7 +515,7 @@ private Class<?> computeParameterType() {
512515
if (method == null) {
513516
return void.class;
514517
}
515-
if (KotlinDetector.isKotlinType(getContainingClass())) {
518+
if (KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(getContainingClass())) {
516519
return KotlinDelegate.getReturnType(method);
517520
}
518521
return method.getReturnType();

spring-core/src/main/java/org/springframework/core/Nullness.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,16 @@ public enum Nullness {
7777
*/
7878
NON_NULL;
7979

80+
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
81+
8082

8183
/**
8284
* Return the nullness of the return type for the given method.
8385
* @param method the source for the method return type
8486
* @return the corresponding nullness
8587
*/
8688
public static Nullness forMethodReturnType(Method method) {
87-
if (KotlinDetector.isKotlinType(method.getDeclaringClass())) {
89+
if (KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(method.getDeclaringClass())) {
8890
return KotlinDelegate.forMethodReturnType(method);
8991
}
9092
return (hasNullableAnnotation(method) ? Nullness.NULLABLE :
@@ -97,7 +99,7 @@ public static Nullness forMethodReturnType(Method method) {
9799
* @return the corresponding nullness
98100
*/
99101
public static Nullness forParameter(Parameter parameter) {
100-
if (KotlinDetector.isKotlinType(parameter.getDeclaringExecutable().getDeclaringClass())) {
102+
if (KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(parameter.getDeclaringExecutable().getDeclaringClass())) {
101103
// TODO Optimize when kotlin-reflect provide a more direct Parameter to KParameter resolution
102104
MethodParameter methodParameter = MethodParameter.forParameter(parameter);
103105
return KotlinDelegate.forParameter(methodParameter.getExecutable(), methodParameter.getParameterIndex());
@@ -124,7 +126,7 @@ public static Nullness forMethodParameter(MethodParameter methodParameter) {
124126
* @return the corresponding nullness
125127
*/
126128
public static Nullness forField(Field field) {
127-
if (KotlinDetector.isKotlinType(field.getDeclaringClass())) {
129+
if (KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(field.getDeclaringClass())) {
128130
return KotlinDelegate.forField(field);
129131
}
130132
return (hasNullableAnnotation(field) ? Nullness.NULLABLE :

spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,16 +360,19 @@ private static List<String> toDistinctUnmodifiableList(String factoryType, List<
360360
*/
361361
static final class FactoryInstantiator<T> {
362362

363+
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
364+
363365
private final Constructor<T> constructor;
364366

367+
365368
private FactoryInstantiator(Constructor<T> constructor) {
366369
ReflectionUtils.makeAccessible(constructor);
367370
this.constructor = constructor;
368371
}
369372

370373
T instantiate(@Nullable ArgumentResolver argumentResolver) throws Exception {
371374
Object[] args = resolveArgs(argumentResolver);
372-
if (KotlinDetector.isKotlinType(this.constructor.getDeclaringClass())) {
375+
if (KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(this.constructor.getDeclaringClass())) {
373376
return KotlinDelegate.instantiate(this.constructor, args);
374377
}
375378
return this.constructor.newInstance(args);

spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
7575

7676
private static final Set<Class<?>> BOOLEAN_TYPES = Set.of(Boolean.class, boolean.class);
7777

78+
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
79+
80+
7881
private final boolean allowWrite;
7982

8083
private final Map<PropertyCacheKey, InvokerPair> readerCache = new ConcurrentHashMap<>(64);
@@ -558,7 +561,7 @@ public PropertyAccessor createOptimalAccessor(EvaluationContext context, @Nullab
558561

559562
private static boolean isKotlinProperty(Method method, String methodSuffix) {
560563
Class<?> clazz = method.getDeclaringClass();
561-
return KotlinDetector.isKotlinType(clazz) &&
564+
return KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(clazz) &&
562565
KotlinDelegate.isKotlinProperty(method, methodSuffix);
563566
}
564567

spring-web/src/main/java/org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
*/
7373
public abstract class AbstractNamedValueMethodArgumentResolver implements HandlerMethodArgumentResolver {
7474

75+
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
76+
7577
private final @Nullable ConfigurableBeanFactory configurableBeanFactory;
7678

7779
private final @Nullable BeanExpressionContext expressionContext;
@@ -103,7 +105,7 @@ public AbstractNamedValueMethodArgumentResolver(@Nullable ConfigurableBeanFactor
103105

104106
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
105107
MethodParameter nestedParameter = parameter.nestedIfOptional();
106-
boolean hasDefaultValue = KotlinDetector.isKotlinType(parameter.getDeclaringClass()) &&
108+
boolean hasDefaultValue = KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(parameter.getDeclaringClass()) &&
107109
KotlinDelegate.hasDefaultValue(nestedParameter);
108110

109111
Object resolvedName = resolveEmbeddedValuesAndExpressions(namedValueInfo.name);

spring-web/src/main/java/org/springframework/web/method/support/InvocableHandlerMethod.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public class InvocableHandlerMethod extends HandlerMethod {
6666

6767
private static final Class<?>[] EMPTY_GROUPS = new Class<?>[0];
6868

69+
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
70+
6971

7072
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
7173

@@ -247,7 +249,7 @@ public void setMethodValidator(@Nullable MethodValidator methodValidator) {
247249
protected @Nullable Object doInvoke(@Nullable Object... args) throws Exception {
248250
Method method = getBridgedMethod();
249251
try {
250-
if (KotlinDetector.isKotlinType(method.getDeclaringClass())) {
252+
if (KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(method.getDeclaringClass())) {
251253
if (KotlinDetector.isSuspendingFunction(method)) {
252254
return invokeSuspendingFunction(method, getBean(), args);
253255
}

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ public class InvocableHandlerMethod extends HandlerMethod {
8585

8686
private static final Object NO_ARG_VALUE = new Object();
8787

88+
private static final boolean KOTLIN_REFLECT_PRESENT = KotlinDetector.isKotlinReflectPresent();
89+
8890

8991
private final HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
9092

@@ -197,12 +199,17 @@ public Mono<HandlerResult> invoke(
197199
}
198200
}
199201
Object value;
202+
boolean isSuspendingFunction;
200203
Method method = getBridgedMethod();
201-
boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
202204
try {
203-
value = (KotlinDetector.isKotlinType(method.getDeclaringClass()) ?
204-
KotlinDelegate.invokeFunction(method, getBean(), args, isSuspendingFunction, exchange) :
205-
method.invoke(getBean(), args));
205+
if (KOTLIN_REFLECT_PRESENT && KotlinDetector.isKotlinType(method.getDeclaringClass())) {
206+
isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
207+
value = KotlinDelegate.invokeFunction(method, getBean(), args, isSuspendingFunction, exchange);
208+
}
209+
else {
210+
isSuspendingFunction = false;
211+
value = method.invoke(getBean(), args);
212+
}
206213
}
207214
catch (IllegalArgumentException ex) {
208215
assertTargetBean(getBridgedMethod(), getBean(), args);

0 commit comments

Comments
 (0)