在一个Java类中使用的lambda的最大数量是多少? [英] What is the maximum number of lambdas used in one Java class?

查看:262
本文介绍了在一个Java类中使用的lambda的最大数量是多少?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个纯粹的概念性问题。

This is a purely conceptual question.

Java 8中的Lambdas转换为使用 invokedynamic

Lambdas in Java 8 are converted to methods that get invoked using the invokedynamic.

如果一个类可以拥有的最大方法数有JVM限制,这是否意味着一个类中使用的最大lambda数也受到严格限制通过JVM?

If there is a JVM limitation for a maximum number of methods that one class can have, does this mean that the maximum number of lambdas used in one class is also strictly limited by JVM?

这个问题几乎与这个问题相同吗? 方法的最大数量是多少Java类可以有什么?

Is this question pretty much equal to this one? What is the maximum number of methods a Java class can have?

推荐答案

Java语言规范没有规定限制,所以我们只有技术限制在那。该规范也没有强制要求特定的编译形式,因此即使技术限制也是模糊的。

The Java Language Specification does not mandate a limit, so we only have technical limitations on that. The specification also doesn’t mandate a particular compiled form, so even the technical limitations are fuzzy.

Lambda表达式被编译成托管主体的类文件的方法lambda表达式,但这不是严格要求的。最值得注意的是,表单的简单表达 foo - > bar(foo)可以像方法引用一样编译。此外,可以使用相同的方法编译相同的lambda表达式。这是一个目前没有发生的优化,它也使调试更难,但原则上,它是允许的。

Lambda expressions are compiled into methods of the class file hosting the body of the lambda expression, but this isn’t strictly required. Most notably, simple expression of the form foo -> bar(foo) could get compiled like method references. Further, identical lambda expressions could get compiled using the same method. This is an optimization that doesn’t currently happen and it also makes debugging harder, but in principle, it is allowed.

此外,智能编译器可以开始生成辅助类托管lambda机构,当它检测到即将到达限制的不太可能的情况。

Also, a smart compiler could start generating auxiliary classes hosting lambda bodies, when it detects the unlikely case that the limit is about to be reached.

使用当前的直接实现,最大方法数,即65535 ,影响可能的lambda表达式的最大数量,但这并不意味着我们可以创建65535个lambda表达式。

With the current straight-forward implementation, the maximum number of methods, i.e. 65535, affects the maximum number of possible lambda expressions, but this doesn’t imply that we can create 65535 lambda expressions.

例如,必须至少有一个(源代码)包含lambda表达式的方法,该表达式将创建功能接口的实例。创建站点的最小指令大小是唯一的 invokedynamic 指令,具有五个字节¹。由于方法的最大代码大小为65535,并且 return 指令至少需要一个by,因此最多可以 65534/5 = = 13106 一个方法中的lambda表达式,因此尝试创建更多需要将它们放在不同的方法中,从而减少了lambda表达式可用的方法数量。您可以使用嵌套的lambda表达式解决这个问题,即 x - > y - > z 但即使嵌套也有实际限制

For example, there must be at least one (source code) method containing the lambda expression, which will create the instance of the functional interface. The minimum instruction size of a creation site is a sole invokedynamic instruction having five bytes¹. Since the maximum code size of a method is 65535 and we need at least one by for the return instruction, there can be at most 65534/5 == 13106 lambda expressions in one method, so trying to create more requires to place them in different methods, reducing the number of methods available to lambda expressions. You can work-around this by using nested lambda expressions, i.e. x -> y -> z, but even nesting has practical limits.

当前编译器使用为每个合成方法生成唯一名称的命名方案,因此它们需要单独的常量池条目。因此,有了独特的实现方法,每个lambda创建站点都需要一个名称条目,名称和类型引用名称,MethodRef引用名称和类型以及(总是相同)声明类,方法句柄引用MethodRef和引用方法句柄的invokedynamic条目。这使得每个lambda表达式总共有五个常量池条目,并且由于常量池限制为65534个条目,并且我们需要一些条目用于其他目的,计算为65500/5,因此与当前编译器实现最大lambda表达式的数量是13,100 。假设它们都具有相同的签名...

The current compilers use naming schemes that produce unique names for each synthetic method, so they need individual constant pool entries. So having unique implementation methods, each lambda creation site will need an entry for the name, the name&type referring to the name, a "MethodRef" referring to the name&type and the (always the same) declaration class, a method handle referring to the "MethodRef" and an invokedynamic entry referring to the method handle. This make a total of five constant pool entries per lambda expression and since the constant pool is limited to 65534 entries, and we need some entries for other purposes, the calculation is 65500/5, so with the current compiler implementations the maximum number of lambda expressions is 13,100. Assuming they all have the same signature…

在使用 javac 的练习测试中(1.8u111)我可以编译一个具有相同签名的13,098个lambda表达式的类文件,甚至在发生错误太多常量之前禁用了生成调试符号的13,100。在该测试类中,我将lambda表达式放入两个构造函数中,因为至少有一个构造函数必须存在,并且两者都可以共享名称条目。我认为,使用标准编译器无法获得更多。

In a practice test with javac (1.8u111) I could compile a class file with 13,098 lambda expressions of the same signature and even exactly 13,100 with generation of debugging symbols disabled, before the error "too many constants" appeared. In that test class, I put the lambda expressions into two constructors, as at least one constructor must be present anyway and both can share the name entry. I think, you can’t get more with a standard compiler.

如果你想解除由在命名方案中,您仍然必须遵守每个方法必须可区分的规则,因此它必须至少与其他方法的名称或签名不同。如果您尝试达到理论最大值,则必须将 n 不同的方法名称与 m 不同的签名组合以允许 n×m 不同的方法,因此65535方法将需要至少256个名称条目和256个签名条目。您仍然拥有唯一的名称和类型组合,因此每个lambda表达式需要其他四个条目,最终会有16,247个可能的lambda表达式。由于它们远小于65535,因此您可以处理较小的名称和类型组合,即将128个名称与128个签名组合在一起,为创建网站提供更多条目,即具有16311个可能的lambda表达式。如果您将签名字符串滥用为方法名称(只要签名不包含引用类型,则可以在字节代码级别上工作)。

If you want to lift the limitation imposed by the naming scheme, you still have to adhere to the rule that each method must be distinguishable, so it must differ at least by either, name or signature, from other methods. If you try to reach the theoretical maximum, you’ll have to combine n distinct method names with m distinct signatures to allow n×m distinct methods, so 65535 methods will require at least 256 name entries and 256 signature entries. You still have unique name&type combinations, so you will need the other four entries per lambda expressions, ending up with 16,247 possible lambda expressions. Since these are far less than 65535, you can cope with lesser name&type combinations, i.e. combine 128 names with 128 signatures, having more entries for the creation sites, i.e. having 16311 possible lambda expression. Some more if you abuse the signature strings as method names (which works on the byte code level, as long as the signatures don’t contain reference types).

For(显着)更多,你必须停止为每个lambda表达式生成不同的方法。

For (significantly) more, you have to stop generating distinct methods for each lambda expression.

¹将产生有效的字节码。在源代码级别,lambda表达式不是语句,因此更多代码,例如需要赋值给变量。

¹ that would make valid bytecode. On source code level, lambda expression aren’t statements, so more code, e.g. an assignment to a variable, is required.

这篇关于在一个Java类中使用的lambda的最大数量是多少?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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