I recently added an interface for QuickTheories:

```java@FunctionalInterfacepublic interface QuadFunction<A, B, C, D, E> { E apply(A a, B b, C c, D d); } ` ` `Copy the code

This makes me wonder how many type parameters a method can support at most. As far as I know, there is no mention of this problem in the Java language specification.

I guess there are two limitations:

  1. Set limits in the compiler, such as 255 or 65535.
  2. The compiler sets limits for unexpected situations, such as stack overflows or similarly unpredictable situations.

I didn’t want to poke around in C++ source code, so I decided to start with the compiler 2. I wrote a Python script that used binary lookup to determine the minimum number of arguments that would cause the compiler to report an error. The full script can be found in the Github repository.

The generation method is simple. Fortunately, as long as

declare it like this, without actually using it:
,>

```pythondef 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("}")```
Copy the code

Binary search results are as follows:

```shell>>> error: UTF8 representation for string "<A1:Ljava/lang/Objec..." is too long for the constant pool>>> largest type: 2776```
Copy the code

The error message above is a little hard to understand, but with hindsight you can still see the limit size. The class file generated by the compiler contains many strings, including the signature of each method in the class. These strings are stored in the constant pool, which is up to 65535 bytes in the JVM specification.

So none of the previous guesses were entirely correct. The maximum number of type parameters is not fixed and depends on the situation. However, it is not the compiler itself that causes error 3, but the JVM class file format that limits the maximum number of type arguments. Although the JVM does not handle generics, the conclusion is correct.

This means that the maximum number of type parameters depends entirely on how method 4 is defined. I tried A new type parameter encoding using write_type_compact in script files, using all legal ASCII characters (A-z, A-z, $, and _). This implementation is a bit complicated; you can use 0-9 but not as an initial character for an identifier, and you can’t use Java keywords. By replacing if and do with utF-8 characters of the same length, the maximum number of arguments is increased from 2776 to 3123.

_A is a valid Java identifier, but _ is not. This is not very convenient. Fortunately, the script managed to generate 3,392 2-byte type arguments without using _, so I didn’t feel the need to consider _ as the first character.

One more trick

Decompiles the class file and finds that most of the 65536 characters are repeated Ljava/lang/Object; String, not the type argument I generated. Because of the lack of type parameter definition information, class files assume that they inherit Object objects, and similar information is contained in method signatures. To do this, I modified the build script and fixed the problem.

Loop key code:

```pythons = type_var(i)f.write(s)if (s ! = 'A'): f.write(" extends A")```Copy the code

Except for one instance that inherits Java /lang/Object, all other type parameters inherit from type A. After modification, the maximum number of parameters that can be compiled is increased to 9851.

So far, the maximum number of type parameters has increased considerably. Of course, you can continue to improve character encodings, such as using non-ASCII Unicode identifiers.

None of that matters

It’s hard to imagine anyone reaching this limit in actual programming. Code generation sometimes reaches the limits of a language or compiler, but it seems unlikely to use hundreds or thousands of type parameters.

Still, if I were the King of Java, I would limit class and method type arguments to 255. It seems better to have an explicit number limit, even if it may only affect one program in a million.

  1. (§ 4.4) [3], [§ 8.1.2] [4], [§ 9.1.2] [5], [§ 8.4.4] [6], [§ 8.8.4] [7] are associated with the type parameter of method or class, but did not mention the biggest allows the use of many parameters. [↩] [8]
  2. Finishing the last line of this article, I suddenly remember that while Hotspot uses C++, javac is written in Java. If I had realized this before I started, I might have experimented instead of reading the source code. Other people’s code is hell. [↩] [9]
  3. The space after the comma doesn’t matter because the compiler normalizes the output. [↩] [10]
  4. This also means that it doesn’t really matter which JVM you use. For completeness, I experimented with OpenJDK 1.8.0191-b13 on Fedora 29. [↩] [11]
! [Java method support at most how many type parameter] (https://p1-tt.byteimg.com/origin/pgc-image/eaf9c51c78a7403db059a800165f017f?from=pc)