How many parameters can a Java method define at most
Introduction: In the JVM, how many parameters can a Java method define at most? This is a very boring question. Even if you can define 10,000 or 100,000, who would really do it. But as a coder, isn't the most important thing to be curious? Without curiosity, what is the difference from a salted fish? The author of this article is such a curious coder.
In the JVM, how many parameters can a Java method define at most? This is a very boring question. Even if you can define 10,000 or 100,000, who would really do it.
But as a coder, isn't the most important thing to be curious? Without curiosity, what is the difference from a salted fish? The author of this article is such a curious coder.
I recently added an interface to my QuickTheories fork:
@FunctionalInterface
public interface QuadFunction {
E apply(A a, B b, C c, D d);
}
What makes me curious is how many type parameters this method can have. So far, I dare say, the Java language specification doesn't address this issue.
I have two guesses as to what the implementation-defined limit might be:
The compiler sets a predictable limit like 255 or 65535.
The compiler's emergent behavior can set unexpected limits due to implementation details (stack overflow or something equally unpredictable/irrelevant).
I didn't want to test my poor C++ skills on source code, so I decided to just test what the compiler did. I wrote a Python script that uses binary search to find the least error-causing type parameter. The complete script is in the Github repo.
The generation method is simple. Fortunately, we don't have to use any type parameters, just emit them as:
def write_type_plain(count):
with open('Test.java', 'w') as f:
f.write("public class Test{n")
f.write("public <")
for i in range(count):
if (i > 0):
f.write(", ")
f. write("A" + str(i + 1))
f.write("> void testMethod() {}")
f.write("}")
Running a binary search yields the following output:
>>> error: UTF8 representation for string " >>> largest type: 2776
The bug was a bit obscure, but predictable in hindsight. The class file generated by the compiler contains many strings, including the method signature of each method in the class. These strings are stored in a constant pool whose entries are up to 65535 bytes, a limit imposed by the JVM specification.
So, none of my previous guesses were entirely correct. The maximum number of type parameters is an emergent property, not an explicit decision. However, it is not the implementation of the compiler itself that is causing the error.
In contrast, the JVM's class file format limits the number of type parameters that can be represented in a class file. This is true, even though the JVM doesn't know anything about generics. This also means that the maximum number of type parameters depends entirely on how the method is written.
I tried a new method of encoding type parameters (write_Type_Compact in the previously linked file), using the full legal ASCII characters (A-Z, a-z, $ and _). The implementation is a bit overly complicated, because characters 0-9 can be used, but not initial characters of identifiers, because Java keywords cannot appear as type parameters. I just replaced the short words "if" and "do" with equal-length UTF-8 characters. A more compact encoding increases the number of parameters from 2776 to 3123.
Inconveniently, _A is a legal Java identifier, but _ is not. Thankfully, my encoding generates 3392 2-byte type parameters without using the initial_, so I don't see the need for bookkeeping to emit the initial_.
One more trick
Unpacking the class file shows that most of the 65536 characters are not my generated type parameters but duplicate instances of the substring Ljava/lang/object . Because no information is provided about the type parameters, the class files show that they extend Object and encode it in the method signature. I modified the generator to fix this.
The key part of the loop is:
s = type_var(i)
f.write(s)
if (s != 'A'):
f.write("extends A")
In the type parameter, all but one instance java/Lang/Object is replaced with A. After making this change, a method with 9851 type parameters compiles.
Since the number of parameters has increased a lot, the code I'm using definitely needs tweaking. Using non-ASCII Unicode identifiers may be a must for complete efficiency, but I'm happy to simply point out that it can be done.
none of this matters
It's hard to imagine anyone hitting that limit. Code generation sometimes hits language or compiler limits, but even the generated code seems unlikely to use hundreds or thousands of type parameters.
Still, if I were a rule maker, I would consider explicitly disallowing any class or method to have more than 255 type parameters. An explicit limit seems better, even if it only affects one in a million programs.
In the JVM, how many parameters can a Java method define at most? This is a very boring question. Even if you can define 10,000 or 100,000, who would really do it.
But as a coder, isn't the most important thing to be curious? Without curiosity, what is the difference from a salted fish? The author of this article is such a curious coder.
I recently added an interface to my QuickTheories fork:
@FunctionalInterface
public interface QuadFunction {
E apply(A a, B b, C c, D d);
}
What makes me curious is how many type parameters this method can have. So far, I dare say, the Java language specification doesn't address this issue.
I have two guesses as to what the implementation-defined limit might be:
The compiler sets a predictable limit like 255 or 65535.
The compiler's emergent behavior can set unexpected limits due to implementation details (stack overflow or something equally unpredictable/irrelevant).
I didn't want to test my poor C++ skills on source code, so I decided to just test what the compiler did. I wrote a Python script that uses binary search to find the least error-causing type parameter. The complete script is in the Github repo.
The generation method is simple. Fortunately, we don't have to use any type parameters, just emit them as:
def write_type_plain(count):
with open('Test.java', 'w') as f:
f.write("public class Test{n")
f.write("public <")
for i in range(count):
if (i > 0):
f.write(", ")
f. write("A" + str(i + 1))
f.write("> void testMethod() {}")
f.write("}")
Running a binary search yields the following output:
>>> error: UTF8 representation for string "
The bug was a bit obscure, but predictable in hindsight. The class file generated by the compiler contains many strings, including the method signature of each method in the class. These strings are stored in a constant pool whose entries are up to 65535 bytes, a limit imposed by the JVM specification.
So, none of my previous guesses were entirely correct. The maximum number of type parameters is an emergent property, not an explicit decision. However, it is not the implementation of the compiler itself that is causing the error.
In contrast, the JVM's class file format limits the number of type parameters that can be represented in a class file. This is true, even though the JVM doesn't know anything about generics. This also means that the maximum number of type parameters depends entirely on how the method is written.
I tried a new method of encoding type parameters (write_Type_Compact in the previously linked file), using the full legal ASCII characters (A-Z, a-z, $ and _). The implementation is a bit overly complicated, because characters 0-9 can be used, but not initial characters of identifiers, because Java keywords cannot appear as type parameters. I just replaced the short words "if" and "do" with equal-length UTF-8 characters. A more compact encoding increases the number of parameters from 2776 to 3123.
Inconveniently, _A is a legal Java identifier, but _ is not. Thankfully, my encoding generates 3392 2-byte type parameters without using the initial_, so I don't see the need for bookkeeping to emit the initial_.
One more trick
Unpacking the class file shows that most of the 65536 characters are not my generated type parameters but duplicate instances of the substring Ljava/lang/object . Because no information is provided about the type parameters, the class files show that they extend Object and encode it in the method signature. I modified the generator to fix this.
The key part of the loop is:
s = type_var(i)
f.write(s)
if (s != 'A'):
f.write("extends A")
In the type parameter, all but one instance java/Lang/Object is replaced with A. After making this change, a method with 9851 type parameters compiles.
Since the number of parameters has increased a lot, the code I'm using definitely needs tweaking. Using non-ASCII Unicode identifiers may be a must for complete efficiency, but I'm happy to simply point out that it can be done.
none of this matters
It's hard to imagine anyone hitting that limit. Code generation sometimes hits language or compiler limits, but even the generated code seems unlikely to use hundreds or thousands of type parameters.
Still, if I were a rule maker, I would consider explicitly disallowing any class or method to have more than 255 type parameters. An explicit limit seems better, even if it only affects one in a million programs.
Related Articles
-
A detailed explanation of Hadoop core architecture HDFS
Knowledge Base Team
-
What Does IOT Mean
Knowledge Base Team
-
6 Optional Technologies for Data Storage
Knowledge Base Team
-
What Is Blockchain Technology
Knowledge Base Team
Explore More Special Offers
-
Short Message Service(SMS) & Mail Service
50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00