This commit is contained in:
Looly 2023-03-25 07:26:59 +08:00
parent dacb489c12
commit af1ac9c121
3 changed files with 47 additions and 19 deletions

View File

@ -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<MethodHandle>) () -> MethodHandles.lookup().unreflect(method)).get();
instantiatedMethodType = MethodType.methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes());
} else {
final Constructor<?> constructor = (Constructor<?>) executable;
implMethod = ((SerSupplier<MethodHandle>) () -> 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

View File

@ -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方法

View File

@ -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);
}
}
/**
* 查找指定方法的方法句柄<br>
* 此方法只会查找