Número máximo de parâmetros na declaração do método Java

133

Qual é o número máximo de parâmetros que um método em Java pode ter e por quê?

Estou usando o Java 1.8 em um sistema Windows de 64 bits.

Todas as respostas no StackOverflow sobre isso dizem que o limite técnico é de 255 parâmetros sem especificar o porquê.

Para ser mais preciso, 255 para thismétodos estáticos e 254 para não estáticos ( será o 255º neste caso).

Eu pensei que isso poderia ser descrito em algum tipo de especificação e que simplesmente existe um número máximo de parâmetros estaticamente definido permitido.

Mas isso era válido apenas para inttodos os tipos de 4 bytes . Fiz alguns testes com longparâmetros e só pude declarar 127 parâmetros nesse caso.

Com os Stringparâmetros, o número permitido deduzido do teste é 255 (pode ser porque o tamanho de referência é 4 bytes em Java?).

Mas como eu estou usando um sistema de 64 bits, o tamanho das referências deve ter 8 bytes de largura e, com os Stringparâmetros, o número máximo permitido deve ser 127, semelhante aos longtipos.

Como esse limite é aplicado exatamente?

O limite tem algo a ver com o tamanho da pilha do método?

Nota: Eu realmente não vou usar esses muitos parâmetros em nenhum método, mas essa pergunta é apenas para esclarecer o comportamento exato.

userv
fonte
39
7, se você não quiser enlouquecer com a legibilidade. (Eu sei o que você está realmente perguntando).
Adam
14
Eu argumentaria <= 4. Qualquer coisa mais provavelmente deve ser embrulhada em um objeto.
Vivin Paliath
4
Por que essa é uma pergunta interessante? Se você está escrevendo um programa e está atingindo esse limite, seu design está errado. Não entendo por que uma pergunta praticamente inútil recebe tantos votos positivos.
Jesper
20
@ Jesper, porque isso questiona o conhecimento da especificação da JVM. Esta pergunta não pergunta "Como fazer isso ou aquilo?" em vez disso, questiona "Por que preciso disso?" ... +1 Pergunta interessante Userv
Amit
2
@ amit exatamente o que eu estava pensando. O OP estava curioso sobre isso.
precisa saber é o seguinte

Respostas:

110

Esse limite é definido na Especificação da JVM :

O número de parâmetros do método é limitado a 255 pela definição de um descritor de método (§4.3.3), em que o limite inclui uma unidade para isso no caso de invocação de método de instância ou interface.

A seção §3.3.3 fornece algumas informações adicionais:

Um descritor de método é válido apenas se representar parâmetros de método com um comprimento total de 255 ou menos, onde esse comprimento inclui a contribuição para isso no caso de invocações de método de instância ou interface.

O comprimento total é calculado somando-se as contribuições dos parâmetros individuais, em que um parâmetro do tipo long ou double contribui com duas unidades para o comprimento e um parâmetro de qualquer outro tipo contribui com uma unidade .

Suas observações foram pontuais; as primitivas de palavra dupla ( long/ double) precisam do dobro do tamanho das variáveis ​​usuais de 4 bytes e das referências de instância do objeto de 4 bytes .

Em relação à última parte da sua pergunta relacionada aos sistemas de 64 bits, a especificação define quantas unidades um parâmetro contribui , que parte da especificação ainda deve ser cumprida, mesmo em uma plataforma de 64 bits, a JVM de 64 bits acomodará 255 parâmetros de instância (como o seu 255 Strings) independentemente do tamanho do ponteiro do objeto interno.

Umberto Raimondi
fonte
10
Eu acrescentaria a essa resposta que, na arquitetura de 64 bits, a pilha também é de 64 bits. Portanto, como a limitação na contagem de parâmetros é vinculada ao tamanho da pilha, a pilha de 64 bits permite armazenar as mesmas 255 referências de objeto. O tratamento específico longe, doubleindependentemente da arquitetura do sistema, ocorre em muitos locais das especificações e parece ser um remanescente da era de 32 bits.
Sergei
Eu estava no processo de editar apenas essa parte :) Concordo, as especificações ainda devem ser respeitadas, mesmo em plataformas diferentes.
Umberto Raimondi
1
Sim, se o número de parâmetros fosse uma função do tamanho da palavra, isso quebraria a portabilidade; não foi possível compilar o mesmo programa Java com sucesso em diferentes arquiteturas.
Vivin Paliath
3
Varargs são transformados em uma matriz de objetos , podem ser usados ​​apenas uma vez na lista de parâmetros e ocupam a última posição. Considerando tudo isso, eu diria que, usando varargs, o número de parâmetros pode ser "estendido" para 254 + Integer.MAX_VALUE (pelo menos para o programador ... os parâmetros ainda são 255), portanto, usando esse truque, você pode ter Integer. Parâmetros do objeto MAX_VALUE.
Umberto Raimondi
1
@MrTsjolder Veja esta resposta para varargs.
Vivin Paliath
11

A Seção 4.3.3 da especificação da JVM contém as informações que você está procurando:

Um descritor de método é válido apenas se representar parâmetros de método com um comprimento total de 255 ou menos, onde esse comprimento inclui a contribuição para isso no caso de invocações de método de instância ou interface. O comprimento total é calculado somando-se as contribuições dos parâmetros individuais, em que um parâmetro do tipo long ou double contribui com duas unidades para o comprimento e um parâmetro de qualquer outro tipo contribui com uma unidade .

Portanto, parece que se a máquina host é de 32 ou 64 bits não afeta o número de parâmetros. Se você notar, a documentação fala em termos de "unidades", onde o comprimento de uma "unidade" é uma função do tamanho da palavra. Se o número de parâmetros diretamente proporcionais ao tamanho da palavra, haveria problemas de portabilidade; você não seria capaz de compilar o mesmo programa Java em arquiteturas diferentes (supondo que pelo menos um método usasse o número máximo de parâmetros na arquitetura com o tamanho de palavra maior).

Vivin Paliath
fonte
10

Encontrei uma questão interessante em um boletim informativo sobre isso, http://www.javaspecialists.eu/archive/Issue059.html

O pool constante por classe ou por interface é limitado a 65535 entradas pelo campo constant_pool_count de 16 bits da estrutura ClassFile. Isso atua como um limite interno para a complexidade total de uma única classe ou interface. A quantidade de código por método não nativo e não abstrato é limitada a 65536 bytes pelos tamanhos dos índices na tabela de exceção do atributo Code, no atributo LineNumberTable e no atributo LocalVariableTable.

O maior número de variáveis ​​locais na matriz de variáveis ​​locais de um quadro criado na chamada de um método é limitado a 65535 pelo tamanho do item max_locals do atributo Code, fornecendo o código do método. Observe que os valores do tipo long e double são considerados para reservar duas variáveis ​​locais e contribuem com duas unidades para o valor max_locals; portanto, o uso de variáveis ​​locais desses tipos reduz ainda mais esse limite.

O número de campos que podem ser declarados por uma classe ou interface é limitado a 65535 pelo tamanho do item fields_count da estrutura ClassFile. Observe que o valor do item fields_count da estrutura ClassFile não inclui campos herdados de superclasses ou superinterfaces.

Matthew Brzezinski
fonte