Número máximo de parámetros en la declaración del método Java

133

¿Cuál es el número máximo de parámetros que puede tener un método en Java y por qué?

Estoy usando Java 1.8 en un sistema Windows de 64 bits.

Todas las respuestas en StackOverflow sobre esto dicen que el límite técnico es 255 parámetros sin especificar por qué.

Para ser precisos, 255 para los thismétodos estáticos y 254 para los no estáticos ( será el 255 en este caso).

Pensé que esto podría describirse en algún tipo de especificación y que simplemente se permite un número máximo de parámetros estáticamente definido.

Pero esto solo era válido para inttodos los tipos de 4 bytes . Hice algunas pruebas con longparámetros, y solo pude declarar 127 parámetros en ese caso.

Con String parámetros, el número permitido que deduje de las pruebas es 255 (¿puede ser porque el tamaño de referencia es de 4 bytes en Java?).

Pero como estoy usando un sistema de 64 bits, el tamaño de las referencias debe ser de 8 bytes de ancho y, por lo tanto, con los Stringparámetros, el número máximo permitido debe ser 127, similar a los longtipos.

¿Cómo se aplica exactamente este límite?

¿El límite tiene algo que ver con el tamaño de la pila del método?

Nota: Realmente no voy a utilizar estos muchos parámetros en ningún método, pero esta pregunta es solo para aclarar el comportamiento exacto.

usuariov
fuente
39
7, si no quieres volverte loco con la legibilidad. (Sé lo que realmente estás preguntando).
Adam
14
Yo diría <= 4. Algo más probablemente debería estar envuelto en un objeto.
Vivin Paliath
44
¿Por qué es esta una pregunta interesante? Si está escribiendo un programa y está llegando a este límite, entonces su diseño es incorrecto. No entiendo por qué una pregunta tan inútil recibe tantos votos positivos.
Jesper
20
@Jesper porque esto cuestiona el conocimiento de la especificación JVM. Esta pregunta no pregunta "¿Cómo hacer esto o aquello?" en cambio, pregunta "¿Por qué necesito eso?" ... +1 Pregunta interesante Userv
Amit
2
@amit exactamente lo que estaba pensando. El OP simplemente tenía curiosidad al respecto.
Evan Carslake

Respuestas:

110

Ese límite se define en la especificación JVM :

El número de parámetros de método está limitado a 255 por la definición de un descriptor de método (§4.3.3), donde el límite incluye una unidad para esto en el caso de invocaciones de método de instancia o interfaz.

La Sección §4.3.3 brinda información adicional:

Un descriptor de método es válido solo si representa parámetros de método con una longitud total de 255 o menos, donde esa longitud incluye la contribución para esto en el caso de invocaciones de método de instancia o interfaz.

La longitud total se calcula sumando las contribuciones de los parámetros individuales, donde un parámetro de tipo largo o doble contribuye dos unidades a la longitud y un parámetro de cualquier otro tipo contribuye con una unidad .

Sus observaciones fueron acertadas, primitivas de doble palabra (long / double) necesitan el doble del tamaño de las variables habituales de 4 bytes y referencias de instancia de objeto de 4 bytes .

Con respecto a la última parte de su pregunta relacionada con los sistemas de 64 bits, la especificación define cuántas unidades contribuye un parámetro , esa parte de la especificación debe cumplirse incluso en una plataforma de 64 bits, la JVM de 64 bits acomodará 255 parámetros de instancia (como su 255 Strings) independientemente del tamaño del puntero del objeto interno.

Umberto Raimondi
fuente
10
Agregaría a esta respuesta que en la arquitectura de 64 bits, la pila también es de 64 bits. Entonces, dado que la limitación en el recuento de parámetros está vinculada al tamaño de la pila, la pila de 64 bits permite almacenar las mismas 255 referencias de objeto. El tratamiento específico longe doubleindependientemente de la arquitectura del sistema se produce en muchos lugares de la especificación y parece ser un remanente de la era de 32 bits.
Sergei
Estaba en el proceso de editar solo esa parte :) De acuerdo, la especificación debe respetarse incluso en diferentes plataformas.
Umberto Raimondi
1
Sí, si el número de parámetros fuera una función del tamaño de la palabra, eso rompería la portabilidad; no podría compilar el mismo programa Java con éxito en diferentes arquitecturas.
Vivin Paliath 01 de
3
Los Varargs se convierten en una matriz de Objetos , se pueden usar solo una vez en la lista de parámetros y ocupan la última posición. Considerando todo esto, diría que usando varargs el número de parámetros puede "extenderse" a 254 + Integer.MAX_VALUE (al menos para el programador ... los parámetros siguen siendo 255), así que usando ese truco puedes tener Integer. Parámetros de objeto MAX_VALUE.
Umberto Raimondi
1
@MrTsjolder Eche un vistazo a esta respuesta para varargs.
Vivin Paliath 01 de
11

La Sección 4.3.3 de la especificación JVM tiene la información que está buscando:

Un descriptor de método es válido solo si representa parámetros de método con una longitud total de 255 o menos, donde esa longitud incluye la contribución para esto en el caso de invocaciones de método de instancia o interfaz. La longitud total se calcula sumando las contribuciones de los parámetros individuales, donde un parámetro de tipo largo o doble contribuye dos unidades a la longitud y un parámetro de cualquier otro tipo contribuye con una unidad .

Por lo tanto, parece que si la máquina host es de 32 bits o de 64 bits no tiene ningún efecto en la cantidad de parámetros. Si observa, la documentación habla en términos de "unidades", donde la longitud de una "unidad" es una función del tamaño de la palabra. Si el número de parámetros es directamente proporcional al tamaño de la palabra, habría problemas de portabilidad; no podría compilar el mismo programa Java en arquitecturas diferentes (suponiendo que al menos un método utilizara el número máximo de parámetros en la arquitectura con el tamaño de palabra más grande).

Vivin Paliath
fuente
10

Encontré un tema interesante en un boletín sobre esto, http://www.javaspecialists.eu/archive/Issue059.html

El grupo constante por clase o por interfaz está limitado a 65535 entradas por el campo constant_pool_count de 16 bits de la estructura ClassFile. Esto actúa como un límite interno en la complejidad total de una sola clase o interfaz. La cantidad de código por método no nativo y no abstracto está limitada a 65536 bytes por el tamaño de los índices en la tabla_excepción del atributo Código, en el atributo LineNumberTable y en el atributo LocalVariableTable.

El mayor número de variables locales en la matriz de variables locales de un marco creado al invocar un método está limitado a 65535 por el tamaño del elemento max_locals del atributo Code que proporciona el código del método. Tenga en cuenta que se considera que los valores de tipo long y double reservan dos variables locales y contribuyen dos unidades hacia el valor max_locals, por lo que el uso de variables locales de esos tipos reduce aún más este límite.

El número de campos que puede declarar una clase o interfaz está limitado a 65535 por el tamaño del elemento fields_count de la estructura ClassFile. Tenga en cuenta que el valor del elemento fields_count de la estructura ClassFile no incluye campos heredados de superclases o superinterfaces.

Matthew Brzezinski
fuente