java - LambdaMetafactory 访问不同 ClassLoader 上的类

标签 java lambda methodhandle lambda-metafactory

我有这个工作正常的代码:

Method getterMethod = Person.class.getDeclaredMethod("getName");

MethodHandles.Lookup lookup = MethodHandles.publicLookup();
Class<?> declaringClass = getterMethod.getDeclaringClass();
Class<?> returnType = getterMethod.getReturnType();
CallSite getterSite = LambdaMetafactory.metafactory(lookup,
    "apply",
    MethodType.methodType(Function.class),
    MethodType.methodType(Object.class, Object.class),
    lookup.findVirtual(declaringClass, getterMethod.getName(), MethodType.methodType(returnType)),
    MethodType.methodType(propertyType, declaringClass));

Function getterFunction = (Function) getterSite.getTarget().invokeExact();

但是,如果 getterMethod 是从不同 ClassLoader 加载的类中的方法,则会抛出:

Caused by: java.lang.invoke.LambdaConversionException: Invalid caller: java.lang.Object
    at java.lang.invoke.AbstractValidatingLambdaMetafactory.<init>(AbstractValidatingLambdaMetafactory.java:118)
    at java.lang.invoke.InnerClassLambdaMetafactory.<init>(InnerClassLambdaMetafactory.java:155)
    at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:299)

如何将我的 ClassLoader 实例传递到 LambdaMetafactory

最佳答案

正如 this answer 所说,lookup modes必须包括 private access被 LambdaMetaFactory 接受。基本上,这意味着调用者指定的类,因为它创建了特定的查找实例,或者查找类有足够的信任将查找对象传递给执行实际调用的代码(例如,当使用指向特定引导方法的 invokedynamic 时就隐含了这一点)。

从 Java 9 开始,有方法 privateLookupIn(Class, MethodHandles.Lookup)尝试获取对另一个类具有私有(private)访问权限的查找对象。正如文档所指定的,访问将根据模块访问规则进行检查,即调用者必须“允许对目标类进行深度反射”。因此,就模块可访问性而言,上述信任的存在仍然是必需的。我想,这就是框架的发展方向,框架管理的代码将向框架开放,以支持此类访问。

如果这不可行,this answer包含一个替代方案,以防您是类加载器的创建者。它使用类加载器的 API 注入(inject)一个新类,该类创建查找对象并允许创建者访问它。可以想象的变化有很多,包括通过让合成类回调到创建者的代码来移交查找对象来确保其安全,而不是将其存储在每个人都可以读取的字段中。

关于java - LambdaMetafactory 访问不同 ClassLoader 上的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48441650/

相关文章:

java - 转换原始数组的通用方法

java - Java 中的 SQL 结果集

java - Java 中 -Xmx 标志的有效值

java - 以编程方式使用 ANTLR4 创建 Java 8 AST

java - 对数组进行排序后获取元素的排名

java - 尽管 MethodHandle 正常,为什么我在 invokeExact 上收到 WrongMethodTypeException

java - 理解 Java 中的数学 : Method that returns the power of 2 of a passed Integer w/o using Java's Math class

java - Lambda 表达式求和

c# - for 和 foreach 在闭包方面有什么区别

java - 如何删除用作监听器的 lambda 表达式/方法句柄?