diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/DefaultMethodInvokingMethodInterceptor.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/DefaultMethodInvokingMethodInterceptor.java index 77c4f87d0c0..72555af44af 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/DefaultMethodInvokingMethodInterceptor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/DefaultMethodInvokingMethodInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Map; +import java.util.function.Supplier; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; @@ -119,29 +120,36 @@ private Lookup getLookup(Class declaringClass, Method privateLookupIn) { */ OPEN { - @Nullable - private final transient Constructor constructor; - - { - Constructor ctor = null; - try { - ctor = Lookup.class.getDeclaredConstructor(Class.class); - ReflectionUtils.makeAccessible(ctor); - } - catch (Exception ex) { - // this is the signal that we are on Java 9 (encapsulated) and can't use the accessible constructor - // approach. - if (!ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) { - throw new IllegalStateException(ex); - } - } - this.constructor = ctor; - } + private volatile boolean constructorResolved; + + private Constructor constructor; + + private final Supplier> constructorSupplier = + () -> { + if (!this.constructorResolved) { + Constructor ctor = null; + try { + ctor = Lookup.class.getDeclaredConstructor(Class.class); + ReflectionUtils.makeAccessible(ctor); + } + catch (Exception ex) { + // this is the signal that we are on Java 9 (encapsulated) and can't use the accessible + // constructor approach. + if (!ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) { + throw new IllegalStateException(ex); + } + } + this.constructor = ctor; + this.constructorResolved = true; + } + return this.constructor; + }; @Override MethodHandle lookup(Method method) throws ReflectiveOperationException { - if (this.constructor != null) { - return this.constructor.newInstance(method.getDeclaringClass()) + Constructor lookupConstructor = this.constructorSupplier.get(); + if (lookupConstructor != null) { + return lookupConstructor.newInstance(method.getDeclaringClass()) .unreflectSpecial(method, method.getDeclaringClass()); } else { @@ -151,7 +159,7 @@ MethodHandle lookup(Method method) throws ReflectiveOperationException { @Override boolean isAvailable() { - return this.constructor != null; + return this.constructorSupplier.get() != null; } }, @@ -160,7 +168,6 @@ boolean isAvailable() { * Fallback {@link MethodHandle} lookup using {@link MethodHandles#lookup() public lookup}. */ FALLBACK { - @Override MethodHandle lookup(Method method) throws ReflectiveOperationException { return doLookup(method, MethodHandles.lookup()); @@ -191,7 +198,7 @@ private static MethodHandle doLookup(Method method, Lookup lookup) throws Reflec * @return the {@link MethodHandleLookup} * @throws IllegalStateException if no {@link MethodHandleLookup} is available. */ - public static MethodHandleLookup getMethodHandleLookup() { + static MethodHandleLookup getMethodHandleLookup() { for (MethodHandleLookup it : MethodHandleLookup.values()) { if (it.isAvailable()) { return it;