diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java index c900eaebc..5d4d5fcc4 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java @@ -4,10 +4,7 @@ import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.map.WeakConcurrentMap; -import cn.hutool.core.reflect.LookupFactory; -import cn.hutool.core.reflect.MethodUtil; -import cn.hutool.core.reflect.ModifierUtil; -import cn.hutool.core.reflect.ReflectUtil; +import cn.hutool.core.reflect.*; import java.io.Serializable; import java.lang.invoke.*; @@ -80,23 +77,23 @@ public class LambdaFactory { .collect(Collectors.toList()); Assert.equals(abstractMethods.size(), 1, "不支持非函数式接口"); ReflectUtil.setAccessible(executable); + + final MethodHandle methodHandle = MethodHandleUtil.unreflect(executable); + final MethodType instantiatedMethodType; + if (executable instanceof Method) { + final Method method = (Method) executable; + instantiatedMethodType = MethodType.methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes()); + } else { + final Constructor constructor = (Constructor) executable; + instantiatedMethodType = MethodType.methodType(constructor.getDeclaringClass(), constructor.getParameterTypes()); + } + final boolean isSerializable = Serializable.class.isAssignableFrom(functionInterfaceType); + final Method invokeMethod = abstractMethods.get(0); final MethodHandles.Lookup caller = LookupFactory.lookup(executable.getDeclaringClass()); final String invokeName = invokeMethod.getName(); final MethodType invokedType = methodType(functionInterfaceType); final MethodType samMethodType = methodType(invokeMethod.getReturnType(), invokeMethod.getParameterTypes()); - final MethodHandle implMethod; - final MethodType instantiatedMethodType; - if (executable instanceof Method) { - final Method method = (Method) executable; - implMethod = ((SerSupplier) () -> MethodHandles.lookup().unreflect(method)).get(); - instantiatedMethodType = MethodType.methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes()); - } else { - final Constructor constructor = (Constructor) executable; - implMethod = ((SerSupplier) () -> MethodHandles.lookup().unreflectConstructor(constructor)).get(); - instantiatedMethodType = MethodType.methodType(constructor.getDeclaringClass(), constructor.getParameterTypes()); - } - final boolean isSerializable = Serializable.class.isAssignableFrom(functionInterfaceType); try { final CallSite callSite = isSerializable ? LambdaMetafactory.altMetafactory( @@ -104,7 +101,7 @@ public class LambdaFactory { invokeName, invokedType, samMethodType, - implMethod, + methodHandle, instantiatedMethodType, FLAG_SERIALIZABLE ) : @@ -113,7 +110,7 @@ public class LambdaFactory { invokeName, invokedType, samMethodType, - implMethod, + methodHandle, instantiatedMethodType ); //noinspection unchecked diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java b/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java index 3777d5e69..5ecf57172 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java @@ -1,6 +1,7 @@ package cn.hutool.core.reflect; import cn.hutool.core.exceptions.UtilException; +import cn.hutool.core.lang.caller.CallerUtil; import cn.hutool.core.util.JdkUtil; import java.lang.invoke.MethodHandles; @@ -42,6 +43,16 @@ public class LookupFactory { } } + /** + * jdk8中如果直接调用{@link MethodHandles#lookup()}获取到的{@link MethodHandles.Lookup}在调用findSpecial和unreflectSpecial + * 时会出现权限不够问题,抛出"no private access for invokespecial"异常,因此针对JDK8及JDK9+分别封装lookup方法。 + * + * @return {@link MethodHandles.Lookup} + */ + public static MethodHandles.Lookup lookup() { + return lookup(CallerUtil.getCaller()); + } + /** * jdk8中如果直接调用{@link MethodHandles#lookup()}获取到的{@link MethodHandles.Lookup}在调用findSpecial和unreflectSpecial * 时会出现权限不够问题,抛出"no private access for invokespecial"异常,因此针对JDK8及JDK9+分别封装lookup方法。 diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java index 791e423dd..af11d0b39 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java @@ -1,12 +1,14 @@ package cn.hutool.core.reflect; -import cn.hutool.core.lang.Assert; import cn.hutool.core.exceptions.UtilException; +import cn.hutool.core.lang.Assert; import cn.hutool.core.text.StrUtil; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; import java.lang.reflect.Method; /** @@ -28,6 +30,24 @@ import java.lang.reflect.Method; */ public class MethodHandleUtil { + /** + * 将{@link Method}或者{@link Constructor} 包装为方法句柄{@link MethodHandle} + * + * @param methodOrConstructor {@link Method}或者{@link Constructor} + * @return 方法句柄{@link MethodHandle} + */ + public static MethodHandle unreflect(final Member methodOrConstructor) { + try { + if (methodOrConstructor instanceof Method) { + return LookupFactory.lookup().unreflect((Method) methodOrConstructor); + } else { + return LookupFactory.lookup().unreflectConstructor((Constructor) methodOrConstructor); + } + } catch (final IllegalAccessException e) { + throw new UtilException(e); + } + } + /** * 查找指定方法的方法句柄
* 此方法只会查找: