Java - SAM类型优化

Tam*_*más 7 java optimization jvm internals java-8

工作文件描述的状态Lambda项目提到所谓的SAM(一个抽象方法)的类型.据我所知,当前的lambda建议不会影响运行时只是编译器,可以实现从lambda表达式到这些类型的自动转换.

我认为在理想情况下,SAM类型的实例可以由函数指针在内部表示.因此,JVM可以避免为这些实例分配内存.

我想知道现代虚拟机是否能够提供这样的优化.

kit*_*yst 6

@Tamás你可能应该阅读Brian Goetz的这篇邮件列表帖子:

http://mail.openjdk.java.net/pipermail/lambda-dev/2011-August/003877.html

基本上,lambda抽象目前使用对象实现.但是,它被设计为允许lambdas的替代实现,这将比类的实例"更小".

您可以将这种情况视为与自动装箱相似 - 整数被装箱为整数,但具有"较小"的表示(如整数).

目前,lambdas必须被装箱到SAM类型的实例,而b/c JVM目前无法用任何较小的构造来表示lambda.将来,可能会有一个新的JVM标准,其中包括"原始函数",它可以将lambda表示为除对象之外的其他东西.

因此,回答你的问题,你提出的优化类型可能是可能的,但它可能会伴随着Java 8之后的"原始函数"而不是特定于实现的特性.


ffr*_*end 5

将单个方法类转换为函数指针并没有什么困难,但是你缺少一件事:lambda表达式不仅仅是函数,它们是闭包.不同之处在于闭包可以捕获外部变量.考虑伪Java中的下一个示例:

public Adder makeAdder(double startNumber) {
    return #{ int number -> number + startNumber}
}

...

int startNumber = 5; 
Adder add5 = makeAdder(startNumber);
add5.invoke(4);  // ==> 9 
Run Code Online (Sandbox Code Playgroud)

在此示例中,通过调用makeAdder()生成的lambda函数引用在此lambda之外定义的变量.这就是为什么它被称为"闭包" - 它们"关闭"它们的自由变量(在这种情况下 - 超过startNumber).要处理这种情况,闭包必须包含指向函数的指针和指向其环境的指针.因此,您获得了一些具有方法和至少一个变量的数据结构.但它不是OOP中对象的定义吗?那么,如果你可以将它作为匿名类的实例,那么创建新类型对象的原因是什么?

然而,可以对这些匿名类进行一些其他优化.您指向的工作文档中提到了其中的一些,例如,推断并有效地使用最终变量(尽管这主要是为了在JVM上允许lambdas,而不是优化代码).生成的匿名类也可能是最终的,并且大多数JVM已经对最终的变量和类进行了很好的优化.

其他改进也可能涉及环境参考 - 那里有很多选择.

  • @TamásHotspot在内部使用TLS(线程本地存储)缓冲区,只有当这些缓冲区在全局堆上完全分配时才会产生同步开销,但这也不是那么昂贵 - 在正常情况下它只是指针增量(I不知道,但几乎肯定是用CAS循环实现的. (3认同)