如何强制lamda定义的新实例化

问题描述 投票:5回答:1

Java-Spec保证给定的lamda定义,例如() -> "Hello World",被编译/转换为一个实现类(每个定义,而不是每个“看起来”相同的出现)。

有什么办法可以强制java-compiler / jvm生成一个新的lamda-definition而不是共享一个常见的?我目前正在实现一个库,它将多个函数部分编织成一个BiFunction,因为java-spec提供了保证,因此受到巨型调用站点的影响(编辑:我更正:Java-Spec不保证单个共享class - 当前的参考实现虽然这样做):

        public <In, Out, A> BiFunction<In, Out, Out> weave(
             Function<? super In, A> getter,
             BiConsumer<? super Out, ? super A> consumer
        ) {
            return (in, out) -> {
                consumer.accept(out, getter.apply(in));
                return out;
            };
        }

通过此代码生成的每个lamda共享相同的lamda定义,因此大多数是不可内联/不可优化的。

java jvm inlining
1个回答
2
投票

在当前实现中,生成的类(或甚至非捕获lambda表达式的实例)的缓存是invokedynamic指令的属性,它将重用在第一次执行时完成的引导结果。

托管在LambdaMetafactory类中的引导方法本身每次调用时都会生成一个新类。因此,当您直接使用此工厂时,您将在当前实现下的每个调用中获得一个新类。

public <In, Out, A> BiFunction<In, Out, Out> weave(
     Function<? super In, A> getter,
     BiConsumer<? super Out, ? super A> consumer) {

    MethodHandles.Lookup l = MethodHandles.lookup();
    try {
        MethodHandle target = l.findStatic(l.lookupClass(), "weaveLambdaBody",
            MethodType.methodType(Object.class, Function.class, BiConsumer.class,
                Object.class, Object.class));
        MethodType t = target.type().dropParameterTypes(0, 2);
        return (BiFunction<In, Out, Out>)LambdaMetafactory.metafactory(l, "apply",
            target.type().dropParameterTypes(2, 4).changeReturnType(BiFunction.class),
            t, target, t) .getTarget().invokeExact(getter, consumer);
    }
    catch(RuntimeException | Error e) {
        throw e;
    }
    catch(Throwable t) {
        throw new IllegalStateException(t);
    }
}
private static <In, Out, A> Out weaveLambdaBody(
    Function<? super In, A> getter,
    BiConsumer<? super Out, ? super A> consumer,
    In in, Out out) {

    consumer.accept(out, getter.apply(in));
    return out;
}

首先,你必须将lambda体变成一种方法。捕获的值首先出现在其参数列表中,然后是功能接口类型的参数。 LambdaMetafactory有关于其用法的详尽文档。

虽然我保留了类型参数用于文档目的,但应该清楚的是,这样的操作会丢失编译时的安全性。

© www.soinside.com 2019 - 2024. All rights reserved.