标签: lambda-metafactory

LambdaMetaFactory具有通用类型的具体实现

我试图使用Java的LambdaMetaFactory动态实现一个通用的拉姆达Handler<RoutingContext>:

public class RoutingContext {
    // ...
}

@FunctionalInterface
public interface Handler<X> {
    public void handle(X arg);
}

public class HomeHandler extends Handler<RoutingContext> {
    @Override
    public void handle(RoutingContext ctx) {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的尝试LambdaMetaFactory:

try {
    Class<?> homeHandlerClass = HomeHandler.class;

    Method method = homeHandlerClass.getDeclaredMethod(
            "handle", RoutingContext.class);
    Lookup lookup = MethodHandles.lookup();
    MethodHandle mh = lookup.unreflect(method);

    MethodType factoryMethodType = MethodType.methodType(Handler.class);
    MethodType functionMethodType = mh.type();
    MethodHandle implementationMethodHandle = mh;

    Handler<RoutingContext> lambda =
            (Handler<RoutingContext>) LambdaMetafactory.metafactory(
                    lookup,
                    "handle", …
Run Code Online (Sandbox Code Playgroud)

java lambda methodhandle java-9 lambda-metafactory

6
推荐指数
2
解决办法
423
查看次数

为什么 LambdaMetafactory 在使用自定义函数接口时会失败(但 Function 工作正常)?

鉴于:

import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.function.Function;

class Testcase
{
    @FunctionalInterface
    public interface MyBuilder1<R>
    {
        R apply(String message);
    }

    @FunctionalInterface
    public interface MyBuilder2<R>
    {
        R apply(Object message);
    }

    public static void main(String[] args) throws Throwable
    {
        Class<?> clazz = IllegalArgumentException.class;

        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodHandle mh = lookup.findConstructor(clazz, MethodType.methodType(void.class, String.class));
        MethodHandle myFunctionConstructor = LambdaMetafactory.metafactory(
            lookup,
            "apply",
            MethodType.methodType(Function.class),
            mh.type().erase(),
            mh,
            mh.type()
        ).getTarget();

        MethodHandle myBuilderConstructor1 = LambdaMetafactory.metafactory(
            lookup,
            "apply",
            MethodType.methodType(MyBuilder1.class),
            mh.type().erase(),
            mh,
            mh.type()
        ).getTarget();

        MethodHandle myBuilderConstructor2 = LambdaMetafactory.metafactory( …
Run Code Online (Sandbox Code Playgroud)

java methodhandle lambda-metafactory

6
推荐指数
1
解决办法
389
查看次数

LambdaMetafactory 访问不同 ClassLoader 上的类

我有这段代码可以正常工作:

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();
Run Code Online (Sandbox Code Playgroud)

但是,如果该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)
Run Code Online (Sandbox Code Playgroud)

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

java lambda methodhandle lambda-metafactory

5
推荐指数
1
解决办法
1669
查看次数

是否有一种快速的反射场访问方法?

我需要一种方法来访问具有反射性质的字段,而不会受到标准反射的性能影响。我已经想出了如何使用特权查找句柄通过 LambdaMetaFactory 使用方法/构造函数执行此操作,但是,我似乎无法弄清楚如何获得字段访问权限。

我以为我可以通过类似 javaassist 的东西生成一个内部类,理论上应该可以访问该字段,但没有成功,抛出一个 IllegalAccessError。

如果我可以重新定义类,那么任务将是微不足道的,因为我可以生成 getter/setter 方法。但是,对于我正在处理的项目,我无法使用代理,因为它需要在运行时加载,而且我必须从工具动态导入附加 api。

任何人都可以在这里指导我正确的方向吗?我研究了 LambdaMetaFactory 如何为方法生成它的接口,并试图用字段来镜像它,但没有成功。如果不重新定义,字段和方法是否有内部不同的东西使这项任务变得不可能?

java lambda-metafactory

5
推荐指数
1
解决办法
132
查看次数

使用 LambdaMetafactory 对从其他类加载器获取的类实例调用单参数方法

基于this stackoverflow answer,我试图使用反射实例化一个类,然后使用它调用一个单参数方法LambdaMetafactory::metafactory(我尝试使用反射,但它很慢)。

更具体地说,我想创建 的一个实例com.google.googlejavaformat.java.Formatter,并formatSource()使用以下签名调用其方法:String formatSource(String input) throws FormatterException.

我定义了以下功能接口:

@FunctionalInterface
public interface FormatInvoker {
  String invoke(String text) throws FormatterException;
}
Run Code Online (Sandbox Code Playgroud)

并试图执行以下代码:

try (URLClassLoader cl = new URLClassLoader(urls.toArray(new URL[urls.size()]))) {
  Thread.currentThread().setContextClassLoader(cl);

  Class<?> formatterClass =
      cl.loadClass("com.google.googlejavaformat.java.Formatter");
  Object formatInstance = formatterClass.getConstructor().newInstance();

  Method method = formatterClass.getMethod("formatSource", String.class);
  MethodHandles.Lookup lookup = MethodHandles.lookup();
  MethodHandle methodHandle = lookup.unreflect(method);
  MethodType type = methodHandle.type();
  MethodType factoryType =
      MethodType.methodType(FormatInvoker.class, type.parameterType(0));
  type = type.dropParameterTypes(0, 1);

  FormatInvoker formatInvoker = (FormatInvoker)
    LambdaMetafactory …
Run Code Online (Sandbox Code Playgroud)

java reflection lambda java-8 lambda-metafactory

4
推荐指数
1
解决办法
1527
查看次数

从 LambdaMetafactory 创建 BiConsumer

我正在尝试通过 LambdaMetafactory 动态创建 BiConsumer 类型的方法引用。我试图应用在https://www.cuba-platform.com/blog/think-twice-before-using-reflection/上找到的两种方法 - createVoidHandlerLambda 和这里Create BiConsumer as Field setter 而不反映Holger 的答案。

但是在这两种情况下我都遇到以下错误:

Exception in thread "main" java.lang.AbstractMethodError: Receiver class org.home.ref.App$$Lambda$15/0x0000000800066040 does not define or inherit an implementation of the resolved method abstract accept(Ljava/lang/Object;Ljava/lang/Object;)V of interface java.util.function.BiConsumer.
    at org.home.ref.App.main(App.java:20)
Run Code Online (Sandbox Code Playgroud)

我的代码是这样的:

public class App {

    public static void main(String[] args) throws Throwable {
        MyClass myClass = new MyClass();
        BiConsumer<MyClass, Boolean> setValid = MyClass::setValid;
        setValid.accept(myClass, true);

        BiConsumer<MyClass, Boolean> mappingMethodReferences = createHandlerLambda(MyClass.class);
        mappingMethodReferences.accept(myClass, true);
    }

    @SuppressWarnings("unchecked")
    public …
Run Code Online (Sandbox Code Playgroud)

java reflection method-reference lambda-metafactory

3
推荐指数
1
解决办法
681
查看次数

Java lambda 元工厂

CallSite lambdaFactory = LambdaMetafactory.metafactory(
   lookup, 
   "call",
   MethodType.methodType(BiConsumer.class), 
   MethodType.methodType(void.class,Long.class), 
      lookup.findVirtual(CallClass.class, "call",       
   MethodType.methodType(void.class,Long.class)),
   MethodType.methodType(void.class));
lambdaFactory.getTarget().invoke(callId);


private void call(Long callId){
     ---
}
Run Code Online (Sandbox Code Playgroud)

我收到此异常 java.lang.invoke.LambdaConversionException: 实例方法 invokeVirtual 调用的参数数量不正确:()void; 0 个捕获参数、0 个功能接口方法参数、0 个实现参数

java lambda-metafactory

1
推荐指数
1
解决办法
951
查看次数