Perché questo superi il limite di 65.535 byte costruttori Java e Inizializzatori statici?

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

  •  16-09-2019
  •  | 
  •  

Domanda

Disclaimer: mi rendo conto che posso generare questo in fase di esecuzione in Java, questo è stato necessario per un caso molto particolare, mentre le prestazioni test del codice. Ho trovato un approccio diverso, in modo da ora questo è solo più di una curiosità che altro pratica.

Ho provato quanto segue come un campo statico, come un campo di istanza, e inizializzato direttamente all'interno del costruttore. Ogni volta che mi eclissi sta informando che o "Il codice del costruttore di TestData () sta superando il limite di 65535 byte" o "Il codice per l'inizializzazione statica sta superando il limite di 65535 byte".

Ci sono 10.000 numeri interi. Se ogni int è di 4 byte (32bits), poi sarebbe non essere 40.000 byte? C'è davvero più di 25,0000 byte di overhead in aggiunta ai dati solo semplicemente costruire la matrice?

I dati sono generati con questo piccolo pezzo di pitone:

#!/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 "};";

Ecco un piccolo esempio:

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
È stato utile?

Soluzione

Ecco il bytecode per inizializzare un array 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]

Quindi, per questa piccola serie ogni elemento richiede 5 byte di bytecode Java. Per l'array grande sia l'indice di matrice e l'indice nella piscina costante useranno 3 byte per maggior parte degli elementi, che porta a 8 byte per elemento dell'array. Così per 10000 gli elementi che ci si può aspettare circa 80kB di byte code.

Il codice per l'inizializzazione grandi array con gli indici a 16 bit è simile al seguente:

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

Altri suggerimenti

letterali di array sono tradotti in codice byte che riempie l'array con i valori, quindi è necessario qualche ulteriore byte per ciascun numero.

Perché non spostare i dati fuori in una risorsa che si carica al tempo di classe di carico in un blocco di inizializzazione statica? Questo può essere fatto facilmente usando MyClass.class.getClassLoader().getResourceAsStream(). Sembra che questo in cui essa appartiene, in ogni caso.

O meglio ancora, creare i valori casuali nel blocco di inizializzazione statica utilizzando gli strumenti Java disponibili. E se avete bisogno ripetibili numeri "casuali", poi basta seminare l'istanza Random con un fisso, ma scelto in modo casuale numero ogni volta.

Oltre ai valori dei numeri interi, il costruttore e l'inizializzazione deve contenere le istruzioni JVM per il caricamento dei numeri interi nella matrice.

Un approccio molto più semplice e più pratico è quello di memorizzare i numeri in un file, sia in formato binario o come testo.

Non so che cosa java inizializza array in questo modo, ma non inizializzo grandi array in modo efficiente.

Credo che la dimensione del codice in caratteri è più di 65535. Non è la memoria occupata da 10000 numeri interi.

Credo che sia possibile che questa è la quantità di memoria necessaria per rappresentare quei int alfanumerico. Credo questo limite potrebbe richiedere il codice stesso, così, ogni int, per esempio:. 1.494.512,072 mila prende effettivamente 10 byte (uno per digit) invece di soli 4 byte utilizzati per l'int32

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top