Skip to content

Commit cd84f16

Browse files
artembilangaryrussell
authored andcommitted
GH-3765 Resolve Lookup ctor lazily via reflection
Fixes #3765 The `DefaultMethodInvokingMethodInterceptor` has several strategies for `default` method invocations in the messaging gateway. One of them is based on the `Lookup` constructor which causes a `WARNING: An illegal reflective access operation has occurred`. This can be done lazily when there is no `MethodHandles.privateLookupIn` in Java version used for the project. * Fix `OPEN` enum value for the `Constructor<Lookup>` to be resolved in a lazy manner via `Supplier` and `boolean` flag **Cherry-pick to `5.5.x`**
1 parent 6a435fb commit cd84f16

File tree

1 file changed

+31
-24
lines changed

1 file changed

+31
-24
lines changed

spring-integration-core/src/main/java/org/springframework/integration/gateway/DefaultMethodInvokingMethodInterceptor.java

+31-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2021 the original author or authors.
2+
* Copyright 2015-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323
import java.lang.reflect.Constructor;
2424
import java.lang.reflect.Method;
2525
import java.util.Map;
26+
import java.util.function.Supplier;
2627

2728
import org.aopalliance.intercept.MethodInterceptor;
2829
import org.aopalliance.intercept.MethodInvocation;
@@ -119,29 +120,36 @@ private Lookup getLookup(Class<?> declaringClass, Method privateLookupIn) {
119120
*/
120121
OPEN {
121122

122-
@Nullable
123-
private final transient Constructor<Lookup> constructor;
124-
125-
{
126-
Constructor<Lookup> ctor = null;
127-
try {
128-
ctor = Lookup.class.getDeclaredConstructor(Class.class);
129-
ReflectionUtils.makeAccessible(ctor);
130-
}
131-
catch (Exception ex) {
132-
// this is the signal that we are on Java 9 (encapsulated) and can't use the accessible constructor
133-
// approach.
134-
if (!ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
135-
throw new IllegalStateException(ex);
136-
}
137-
}
138-
this.constructor = ctor;
139-
}
123+
private volatile boolean constructorResolved;
124+
125+
private Constructor<Lookup> constructor;
126+
127+
private final Supplier<Constructor<Lookup>> constructorSupplier =
128+
() -> {
129+
if (!this.constructorResolved) {
130+
Constructor<Lookup> ctor = null;
131+
try {
132+
ctor = Lookup.class.getDeclaredConstructor(Class.class);
133+
ReflectionUtils.makeAccessible(ctor);
134+
}
135+
catch (Exception ex) {
136+
// this is the signal that we are on Java 9 (encapsulated) and can't use the accessible
137+
// constructor approach.
138+
if (!ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
139+
throw new IllegalStateException(ex);
140+
}
141+
}
142+
this.constructor = ctor;
143+
this.constructorResolved = true;
144+
}
145+
return this.constructor;
146+
};
140147

141148
@Override
142149
MethodHandle lookup(Method method) throws ReflectiveOperationException {
143-
if (this.constructor != null) {
144-
return this.constructor.newInstance(method.getDeclaringClass())
150+
Constructor<Lookup> lookupConstructor = this.constructorSupplier.get();
151+
if (lookupConstructor != null) {
152+
return lookupConstructor.newInstance(method.getDeclaringClass())
145153
.unreflectSpecial(method, method.getDeclaringClass());
146154
}
147155
else {
@@ -151,7 +159,7 @@ MethodHandle lookup(Method method) throws ReflectiveOperationException {
151159

152160
@Override
153161
boolean isAvailable() {
154-
return this.constructor != null;
162+
return this.constructorSupplier.get() != null;
155163
}
156164

157165
},
@@ -160,7 +168,6 @@ boolean isAvailable() {
160168
* Fallback {@link MethodHandle} lookup using {@link MethodHandles#lookup() public lookup}.
161169
*/
162170
FALLBACK {
163-
164171
@Override
165172
MethodHandle lookup(Method method) throws ReflectiveOperationException {
166173
return doLookup(method, MethodHandles.lookup());
@@ -191,7 +198,7 @@ private static MethodHandle doLookup(Method method, Lookup lookup) throws Reflec
191198
* @return the {@link MethodHandleLookup}
192199
* @throws IllegalStateException if no {@link MethodHandleLookup} is available.
193200
*/
194-
public static MethodHandleLookup getMethodHandleLookup() {
201+
static MethodHandleLookup getMethodHandleLookup() {
195202
for (MethodHandleLookup it : MethodHandleLookup.values()) {
196203
if (it.isAvailable()) {
197204
return it;

0 commit comments

Comments
 (0)