Tamaño máximo de un método en Java 7 y 8

82

Sé que un método no puede superar los 64 KB con Java. La limitación nos causa problemas con el código generado a partir de una gramática JavaCC . Tuvimos problemas con Java 6 y pudimos solucionarlo cambiando la gramática. ¿Se ha cambiado el límite para Java 7 o está previsto para Java 8?

Sólo para que quede claro. No necesito un método de más de 64 KB por mí mismo. Pero escribí una gramática que se compila con un método muy extenso.

LaurentG
fuente
4
Enfrenté el mismo problema cuando traté de compilar un enorme código de mierda.
johnchen902
3
Sin información que indique lo contrario, creo que es seguro asumir que este límite se seguirá aplicando en Java 8 ... Por supuesto, otra opción (costosa) podría ser cambiar el motor gramatical por sancochado , lo que le permite escribe tus gramáticas en Java puro.
fge
4
Eche un vistazo a este artículo
Anirudha
7
Personalmente, creo que crear métodos tan grandes es un error en JavaCC . Realmente debería poder difundir su código. Especialmente teniendo en cuenta que la JVM definitivamente no está diseñada para optimizar métodos tan grandes.
Joachim Sauer

Respuestas:

58

Según JVMS7 :

El hecho de que end_pc sea exclusivo es un error histórico en el diseño de la máquina virtual Java: si el código de la máquina virtual Java para un método tiene exactamente 65535 bytes de longitud y termina con una instrucción de 1 byte de longitud, entonces esa instrucción no se puede proteger. por un manejador de excepciones. Un escritor de compiladores puede solucionar este error limitando el tamaño máximo del código de máquina virtual Java generado para cualquier método, método de inicialización de instancia o inicializador estático (el tamaño de cualquier matriz de código) a 65534 bytes.

Pero de esto se trata Java 7. No hay especificaciones finales para Java 8, por lo que nadie (excepto sus desarrolladores) podría responder a esta pregunta.

UPD (2015-04-06) Según JVM8 , también es válido para Java 8.

Andremoniy
fuente
2
¿Realmente hay un "error" en Java que todavía no se ha solucionado? Podría ser una gran limitación, especialmente para la situación de LaurentG.
Francesco Belladonna
3
@ Fire-Dragon-DoL La discusión citada trata solo sobre que el método debe tener un byte menos de longitud de lo que podría haber sido de otra manera. Esto es bastante irrelevante. El límite no se debe a un simple "error" como ese: está en el diseño general del código de bytes y para solucionarlo sería necesario volver a especificarlo en su totalidad.
Marko Topolnik
11

Buena pregunta. Como siempre, debemos ir a la fuente para encontrar la respuesta ( "La especificación de la máquina virtual Java®" ). Sin embargo, la sección no menciona explícitamente un límite (como lo hizo la especificación Java6 VM), pero de manera algo circunspecta:

El mayor número de variables locales en la matriz de variables locales de un marco creado al invocar un método (§2.6) está limitado a 65535 por el tamaño del elemento max_locals del atributo Code (§4.7.3) que da el código del y mediante la indexación de variables locales de 16 bits del conjunto de instrucciones de la máquina virtual Java.

Salud,

Anders R. Bystrup
fuente
5
El "mayor número de variables locales" tiene el mismo valor numérico, pero sigue siendo algo completamente diferente al "tamaño máximo de un método", pidió el OP.
Holger
8

No ha cambiado. El límite de código en los métodos sigue siendo de 64 KB tanto en Java 7 como en Java 8.

Referencias:

  1. De la especificación de máquina virtual Java 7 ( 4.9.1 Restricciones estáticas ):

Las restricciones estáticas en el código de la Máquina Virtual Java en un archivo de clase especifican cómo deben distribuirse las instrucciones de la Máquina Virtual Java en la matriz de código y cuáles deben ser los operandos de instrucciones individuales.

Las restricciones estáticas de las instrucciones en la matriz de código son las siguientes:

  • La matriz de código no debe estar vacía, por lo que el elemento code_length no puede tener el valor 0.
  • El valor del elemento code_length debe ser menor que 65536.
  1. De la especificación de la máquina virtual Java 8 ( 4.7.3 El atributo de código ):

El valor del elemento code_length da el número de bytes en la matriz de código para este método.

El valor de code_length debe ser mayor que cero (ya que la matriz de código no debe estar vacía) y menor que 65536.

Philipp Claßen
fuente
1

Andremoniy ya respondió la java 7parte de esta pregunta, pero parece que en ese momento era pronto para decidir, java 8así que completo la respuesta para cubrir esa parte:

Citando de jvms :

El hecho de que end_pc sea exclusivo es un error histórico en el diseño de la máquina virtual Java: si el código de la máquina virtual Java para un método tiene exactamente 65535 bytes de longitud y termina con una instrucción de 1 byte de longitud, entonces esa instrucción no puede protegerse. por un manejador de excepciones. Un escritor de compiladores puede solucionar este error limitando el tamaño máximo del código generado de la Máquina Virtual Java para cualquier método, método de inicialización de instancia o inicializador estático (el tamaño de cualquier matriz de código) a 65534 bytes.

Como ve, parece que este problema histórico no parece solucionarse al menos en esta versión (Java 8).

mok
fuente
-1

Como solución alternativa, y si tiene acceso al código del analizador, puede modificarlo para que funcione dentro de los límites impuestos por el compilador de JVM ... (suponiendo que no lleve una eternidad encontrar las partes en el código del analizador para modificar)

ombud
fuente