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

use*_*erv 130 java jvm

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

这个限制是如何应用的?

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

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

Umb*_*ndi 109

该限制在JVM规范中定义:

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

§4.3.3节提供了一些额外的信息:

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

总长度是通过对各个参数的贡献求和来计算的,其中long或double类型的参数对长度贡献两个单位,而任何其他类型的参数贡献一个单位.

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

关于与64位系统相关的问题的最后一部分,规范定义了参数贡献了多少单位,即使在64位平台上也必须遵守规范的一部分,64位JVM将容纳255个实例参数(如255 Strings)无论内部对象的指针大小.

  • 我想补充一点,在64位架构上,堆栈也是64位.因此,由于参数计数的限制是堆栈大小限制,因此64位堆栈允许存储相同的255个对象引用.无论系统架构如何,"long"和"double"的具体处理都发生在规范的许多地方,似乎是32位时代的遗留物. (10认同)
  • Varargs被转换为*Object*数组,只能在参数列表中使用一次并占据最后一个位置.考虑到所有这些,我会说使用varargs参数的数量可以"扩展"到254 + Integer.MAX_VALUE(至少对于程序员...参数仍然是255),所以使用这个技巧你可以有Integer. MAX_VALUE对象参数. (3认同)

Viv*_*ath 11

JVM规范的4.3.3节包含您要查找的信息:

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

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


Mat*_*ski 10

我在时事通讯中发现了一个有趣的问题,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项的值不包括从超类或超接口继承的字段.