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


133

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

如何精确应用此限制?

限制与方法的堆栈大小有关吗?

注意:我实际上不会在任何方法中使用这些许多参数,但是这个问题只是为了阐明确切的行为。


39
7,如果您不想疯狂地阅读。(我知道您实际上在问什么)。
亚当

14
我会争辩<= 4。任何其他内容都应该包装成一个对象。
Vivin Paliath

4
为什么这是一个有趣的问题?如果您正在编写程序并且达到此极限,那么您的设计是错误的。我不明白为什么这么一个实际上无用的问题会引起如此多的反对。
杰斯珀,2015年

20
@Jesper,因为这质疑了JVM规范的知识。这个问题不会问“如何做到这一点?” 相反,它质疑“我为什么要这么做?” ... +1有趣的问题Userv
阿米特(Amit)

2
@amit正是我的想法。OP对此很好奇。
埃文·卡斯莱克

Answers:


110

该限制在JVM规范中定义:

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

4.3.3节提供了一些附加信息:

方法描述符仅在表示总长度为255或更短的方法参数时才有效,其中该长度包括实例或接口方法调用时对此的贡献。

通过将各个参数的贡献相加来计算总长度,其中long或double类型的参数对长度贡献两个单位,而其他类型的参数则贡献一个单位

您的发现很明显,双字基元(long/ double)需要两倍于通常的4字节变量和4字节对象实例引用的大小

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


10
我要补充一点,在64位体系结构上,堆栈也是64位。因此,由于参数计数的限制是堆栈大小的限制,因此64位堆栈允许存储相同的255个对象引用。具体的治疗longdouble不管系统架构的出现在规范中的很多地方,似乎是32位时代的遗迹。
Sergei 2015年

我只是在编辑那部分内容:)同意,即使在不同平台上,仍然必须遵守规范。
Umberto Raimondi 2015年

1
是的,如果参数的数量是字长的函数,那将破坏可移植性;您无法在不同架构上成功编译相同的Java程序。
Vivin Paliath,2015年

3
Varargs变成一个Object数组,只能在参数列表中使用一次并占据最后一个位置。考虑到所有这些,我会说使用varargs可以将参数的数量“扩展”到254 + Integer.MAX_VALUE(至少对于程序员来说...参数仍然是255),因此使用该技巧就可以使用Integer。 MAX_VALUE个对象参数。
Umberto Raimondi 2015年

1
@MrTsjolder看看varargs的答案
Vivin Paliath

11

JVM规范的4.3.3节提供了您正在寻找的信息:

方法描述符仅在表示总长度小于或等于255的方法参数时才有效,该长度包括实例或接口方法调用时对此的贡献。通过将各个参数的贡献相加来计算总长度,其中 long或double类型 的参数对长度 贡献两个单位,而其他类型参数则贡献一个单位

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


10

我从时事通讯中找到了一个有趣的问题,http://www.javaspecialists.eu/archive/Issue059.html

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

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

类或接口可以声明的字段数由ClassFile结构的fields_count项的大小限制为65535。请注意,ClassFile结构的fields_count项目的值不包括从超类或超接口继承的字段。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.