Java 方法声明中的最大参数数目

Java 中一个方法可以拥有的最大参数数目是多少? 为什么?

我在一个64位的 Windows 系统上使用 Java 1.8。

StackOverflow 上关于这个问题的所有答案都说技术限制是255个参数,但没有说明原因。

确切地说,静态方法为255,非静态方法为254(this将是本例中的第255个)。

我认为这可以在某种规范中描述,只是静态定义了允许的最大参数数量。

但这只对 int和所有4字节类型有效。 我用 long参数做了一些测试,在这种情况下,我只能声明127个参数。

对于 String参数,我从测试中推断出允许的数字是255(这可能是因为在 Java 中引用大小是4字节?).

但是因为我使用的是64位系统,引用大小应该是8字节宽,所以使用 String参数时,最大允许的数字应该是127,类似于 long类型。

如何确切地应用这一限制?

这个极限和方法的 堆栈大小有什么关系吗?

注意: 我并不打算在任何方法中使用这么多参数,但是这个问题只是为了阐明确切的行为。

37666 次浏览

这一限制在 JVM 规范中有明确规定:

根据方法描述符(4.3.3)定义的方法参数 限制在255的数目,其中在实例或接口方法调用的情况下,限制包括 这个的一个单元。

4.3.3节提供了一些补充信息:

只有当方法描述符表示总长度为255或更小的方法参数时,方法描述符才是有效的,其中该长度包括在实例或接口方法调用的情况下对 这个的贡献。

总长度的计算是通过总和的贡献,各个参数,一个 long 或 double 类型的参数对长度的贡献是两个单位,而另一个类型的参数对长度的贡献是一个单位

您的观察是正确的,双字原语(long/double)需要两倍于通常的4字节变量 和4字节的对象实例引用的大小。

关于你问题的最后一部分与64位系统有关,这个规范定义了多少个 单位参数贡献,即使在64位平台上也是 仍然必须遵守的一部分,64位 JVM 将容纳255个实例参数(比如你的255个 Strings) ,而不管内部对象的指针大小如何。

JVM 规范的4.3.3 部分提供了您需要的信息:

只有当方法描述符表示总长度为255或更小的方法参数时,方法描述符才是有效的,其中该长度包括在实例或接口方法调用的情况下对此的贡献。总长度是通过将各个参数的贡献相加来计算的,其中 型长或双贡献两个单位 到长度和一个 任何其他类型的参数贡献一个单位.

因此,主机是32位还是64位似乎对参数数量没有影响。如果您注意到,文档使用的是“单位”,其中一个“单位”的长度是单词大小的函数。如果参数的数量与单词大小成正比,那么就会出现可移植性问题; 你将无法在不同的架构上编译相同的 Java 程序(假设至少有一种方法使用了单词大小较大的架构上的最大参数数量)。

我在一份时事通讯中发现了一个有趣的问题,http://www.javaspecialists.eu/archive/Issue059.html

ClassFile 结构的16位 Constant _ pool _ count 字段将每个类或每个接口常量池限制为65535个条目。这是对单个类或接口的总复杂度的内部限制。 每个非本机、非抽象方法的代码量被 Code 属性的 eption _ table、 LineNumberTable 属性和 LocalVariableTable 属性中的索引大小限制为65536字节。

在调用方法时创建的框架的局部变量数组中,局部变量的最大数目被 Code 属性中给出方法代码的 max _ local 项的大小限制为65535。请注意,long 和 double 类型的值都被认为保留了两个局部变量,并向 max _ local 值贡献了两个单位,因此使用这些类型的局部变量进一步降低了这个限制。

根据 ClassFile 结构的 fields _ count 项的大小,类或接口可以声明的字段数限制为65535。注意,ClassFile 结构的 fields _ count 项的值不包括从超类或超接口继承的字段。