LambdaMetafactory可以访问其他ClassLoader上的类 [英] LambdaMetafactory to access class on a different ClassLoader

查看:164
本文介绍了LambdaMetafactory可以访问其他ClassLoader上的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段正常运行的代码:

I have this code which works fine:

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加载的类中的方法,则会抛出:

But if the getterMethod is a method from a class loaded from a different ClassLoader, it throws:

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?

How do I pass my ClassLoader instance to the LambdaMetafactory?

推荐答案

所说的答案所说,查找模式必须包含私有访问LambdaMetaFactory接受.基本上,这意味着调用者指定的类,因为它创建了特定的查找实例,或者查找类具有足够的信任度,可以将查找对象传递给进行实际调用的代码(例如,当使用invokedynamic指向特定的引导程序方法时,这是隐含的.

As said by this answer, the lookup modes must include the private access to be accepted by the LambdaMetaFactory. Basically, this implies that either, the caller is the specified class, as it created the particular lookup instance, or the lookup class has enough trust to pass the lookup object to the code which did the actual call (which is e.g. implied when using invokedynamic pointing to a particular bootstrap method).

从Java 9开始,有方法

Starting with Java 9, there is the method privateLookupIn(Class, MethodHandles.Lookup) to attempt to get a lookup object with private access to another class. As the documentation specifies, the access is checked against the module access rules, i.e. the caller must be "allowed to do deep reflection on the target class". So the presence of the trust mentioned above, still is required, now in terms of module accessibility. I suppose, that’s the way to go for frameworks, where the code managed by the framework will be opened to the framework to support such access.

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

If that’s not feasible, this answer contains an alternative, in case you are the creator of the class loader. It uses the class loader’s API to inject a new class which creates the lookup object and allows the creator to access it. There are variations imaginable, including making it secure by letting the synthetic class call back into the creator’s code to hand over the lookup object, instead of storing it in a field where everyone could read it.

这篇关于LambdaMetafactory可以访问其他ClassLoader上的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆