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类型。

这个限制是如何应用的?

该限制是否与该方法的堆栈大小有关?

注意:我并不是真的会在任何方法中使用这些参数,但这个问题只是为了澄清确切的行为。


#1 热门回答(101 赞)

该限制在JVM Specification中定义:

通过定义方法描述符(第4.3.3节),方法参数的数量限制为255,其中在实例或接口方法调用的情况下,限制包括一个单位。

Section§4.3.3给出了一些额外的信息:

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

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

关于与64位系统相关的问题的最后部分,规范定义了参数贡献的单元数量,规范的部分仍然必须在64位平台上符合,64位JVM将容纳255个实例参数(如255Strings)无论内部对象的指针大小如何。


#2 热门回答(11 赞)

JVM规范的Section 4.3.3具有你要查找的信息:

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

因此,看起来主机是32位还是64位对参数的数量没有影响。如果你注意到,文档以"单位"表示,其中一个"单位"的长度是单词大小的函数。如果参数的数量与字大小成正比,则会出现可移植性问题;你将无法在不同的体系结构上编译相同的Java程序(假设至少有一种方法使用具有较大字长的体系结构上的最大参数数)。


#3 热门回答(11 赞)

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

ClassFile结构的16位constant_pool_count字段将每类或每接口常量池限制为65535个条目。这是对单个类或接口的总复杂性的内部限制。每个非本机非抽象方法的代码量由Code属性的exception_table,LineNumberTable属性和LocalVariableTable属性中的索引大小限制为65536字节。在调用方法时创建的帧的局部变量数组中最大数量的局部变量被Code35属性的max_locals项的大小限制为65535,该属性给出了方法的代码。请注意,long和double类型的值都被认为是保留两个局部变量并为max_locals值提供两个单位,因此使用这些类型的局部变量会进一步降低此限制。可以由类或接口声明的字段数量被ClassFile结构的fields_count项的大小限制为65535。请注意,ClassFile结构的fields_count项的值不包括从超类或超接口继承的字段。