Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the maximum number of lambdas used in one Java class?

This is a purely conceptual question.

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

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?

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

like image 280
Grzegorz Piwowarek Avatar asked Nov 29 '16 08:11

Grzegorz Piwowarek


People also ask

How many lambdas can run at once?

There is no maximum concurrency limit for Lambda functions. However, limit increases are granted only if the increase is required for your use case. To avoid throttling, it's a best practice to request a limit increase at least two weeks prior to when the increase is needed.

What is the limit of lambda?

128 MB to 10,240 MB, in 1-MB increments.

What is the maximum number of methods that a Java class can contain?

b) A class should contain an average of less than 30 methods, resulting in up to 900 lines of code.

What is lambda payload limit?

Lambda Payload Limit There is a hard limit of 6mb when it comes to AWS Lambda payload size. This means we cannot send more than 6mb of data to AWS Lambda in a single request.


1 Answers

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 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.

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.

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.

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.

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…

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.


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 (significantly) more, you have to stop generating distinct methods for each lambda expression.


¹ 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.

like image 183
Holger Avatar answered Nov 11 '22 16:11

Holger