¿Por qué esta sobrepase el límite de 65.535 bytes en los constructores de Java y los inicializadores estáticos?

StackOverflow https://stackoverflow.com/questions/788787

  •  16-09-2019
  •  | 
  •  

Pregunta

exención de responsabilidad: Soy consciente de que puedo generar esta en tiempo de ejecución de Java, esto era necesario para un caso muy especial, mientras que el rendimiento probar algo de código. He encontrado un enfoque diferente, por lo que ahora esto es sólo más una curiosidad que otra práctica.

He intentado lo siguiente como un campo estático, como un campo de instancia, y se inicializa directamente dentro del constructor. Todos los eclipses tiempo me está informando que sea "El código de TestData constructor () está excediendo el límite de 65535 bytes" o "El código para el inicializador estático está excediendo el límite de 65535 bytes".

Hay 10.000 enteros. Si cada int es de 4 bytes (32bits), entonces ¿no sería 40.000 bytes? ¿Hay realmente más que 25.0000 bytes de sobrecarga, además de los datos sólo simplemente la construcción de la matriz?

Los datos se genera con este pequeño fragmento de pitón:

#!/usr/bin/python

import random;
print "public final int[] RANDOM_INTEGERS = new int[] {";
for i in range(1,10000):
    print str(int(random.uniform(0,0x7fffffff))) + ",";
print "};";

He aquí una pequeña muestra:

public final int[] RANDOM_INTEGERS = new int[] {
    963056418, 460816633, 1426956928, 1836901854, 334443802, 721185237, 488810483,
    1734703787, 1858674527, 112552804, 1467830977, 1533524842, 1140643114, 1452361499,
    716999590, 652029167, 1448309605, 1111915190, 1032718128, 1194366355, 112834025,
    419247979, 944166634, 205228045, 1920916263, 1102820742, 1504720637, 757008315,
    67604636, 1686232265, 597601176, 1090143513, 205960256, 1611222388, 1997832237,
    1429883982, 1693885243, 1987916675, 159802771, 1092244159, 1224816153, 1675311441,
    1873372604, 1787757434, 1347615328, 1868311855, 1401477617, 508641277, 1352501377,
    1442984254, 1468392589, 1059757519, 1898445041, 1368044543, 513517087, 99625132,
    1291863875, 654253390, 169170318, 2117466849, 1711924068, 564675178, 208741732,
    1095240821, 1993892374, 87422510, 1651783681, 1536657700, 1039420228, 674134447,
    1083424612, 2137469237, 1294104182, 964677542, 1506442822, 1521039575, 64073383,
    929517073, 206993014, 466196357, 1139633501, 1692533218, 1934476545, 2066226407,
    550646675, 624977767, 1494512072, 1230119126, 1956454185, 1321128794, 2099617717,
    //.... to 10,0000 instances
¿Fue útil?

Solución

Este es el código de bytes para la inicialización de una matriz con {1000001, 1000002, 1000003}:

 5  iconst_3
 6  newarray int [10]
 8  dup
 9  iconst_0
10  ldc <Integer 1000001> [12]
12  iastore
13  dup
14  iconst_1
15  ldc <Integer 1000002> [13]
17  iastore
18  dup
19  iconst_2
20  ldc <Integer 1000003> [14]
22  iastore
23  putfield net.jstuber.test.TestArrayInitializingConstructor.data : int[] [15]

Así, por esta pequeña gama cada elemento requiere 5 bytes de código de bytes de Java. Para su arreglo más grande, tanto el índice de matriz y el índice en el conjunto de constantes utilizarán 3 bytes para la mayoría de los elementos, lo que conduce a 8 bytes por elemento de la matriz. Así que para 10000 elementos que tendría que esperar aproximadamente 80 KB de código de bytes.

El código para inicializar grandes matrices con índices de 16 bits es el siguiente:

2016  dup
2017  sipush 298
2020  ldc_w <Integer 100298> [310]
2023  iastore
2024  dup
2025  sipush 299
2028  ldc_w <Integer 100299> [311]

Otros consejos

Los literales de conjunto se traducen en el código de bytes que se llena la matriz con los valores, por lo que necesita un poco más bytes para cada número.

¿Por qué no mover los datos a cabo en un recurso que se carga en el momento de la clase de carga en un bloque inicializador estático? Esto puede hacerse fácilmente mediante el uso de MyClass.class.getClassLoader().getResourceAsStream(). Parece que esta donde debe estar, al menos.

O mejor aún, crear los valores aleatorios en el bloque inicializador estático utilizando las herramientas Java disponible. Y si necesita números repetibles "al azar", a continuación, sólo sembrar la instancia Random con un fijo, pero seleccionadas al azar número cada vez.

Además de los valores de los números enteros, el constructor y el inicializador tiene que contener las instrucciones de la JVM para la carga de los números enteros en la matriz.

Un enfoque mucho más simple y más práctico es almacenar los números en un archivo, ya sea en un formato binario o como texto.

No sé qué Java inicializa matrices de esta manera, pero no inicializar matrices grandes de manera eficiente.

Creo que el tamaño del código de caracteres es más de 65535. No es la memoria que emplea 10.000 enteros.

Creo que es posible que esta es la cantidad de memoria necesaria para representar los enteros de forma alfanumérica. Creo que se podría aplicar este límite para el código en sí, por lo que, cada int, por ejemplo:. 1494512072 realmente tiene 10 bytes (uno por dígitos) en lugar de sólo 4 bytes utilizados para la int32

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top