Pourquoi cela dépasse la limite 65535 octets en Java et constructeurs Initialiseur statiques?

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

  •  16-09-2019
  •  | 
  •  

Question

Disclaimer: Je me rends compte que je peux générer ce à l'exécution en Java, c'était nécessaire pour un cas très particulier en tester les performances du code. J'ai trouvé une approche différente, maintenant c'est un peu plus d'une curiosité que toute pratique.

Je l'ai essayé ce qui suit comme un champ statique, comme un champ d'instance et initialisés directement dans le constructeur. Chaque éclipse de temps me informant que ce soit « Le code du constructeur TestData () dépasse la limite de 65535 octets » ou « Le code de la initialiseur statique dépasse la limite de 65535 octets ».

Il y a 10.000 entiers. Si chaque int est de 4 octets (32bits), alors serait-ce pas 40,000 octets? Est-il vraiment plus que 25,0000 octets de frais généraux, en plus des données qui viennent simplement construire le tableau?

Les données sont générées avec ce petit morceau de python:

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

Voici un petit échantillon:

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
Était-ce utile?

La solution

Voici le bytecode pour initialiser un tableau avec {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]

Donc, pour ce petit tableau chaque élément nécessite 5 octets de code Java. Pour votre plus grand tableau à la fois l'index de tableau et l'indice dans la piscine constante utiliseront 3 octets pour la plupart des éléments, ce qui conduit à 8 octets par élément de tableau. Donc, pour 10000 éléments que vous auriez à attendre à propos 80kB du code octet.

Le code d'initialisation de grands tableaux avec 16 indices de bits ressemble à ceci:

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

Autres conseils

littéraux Array sont convertis dans le code d'octets qui remplit le tableau avec les valeurs, vous devez donc quelques octets de plus pour chaque numéro.

Pourquoi ne pas déplacer les données sur une ressource que vous chargez à temps de chargement de classe dans un bloc d'initialisation statique? Cela peut facilement être fait en utilisant MyClass.class.getClassLoader().getResourceAsStream(). Il semble que ce où il appartient, de toute façon.

Ou mieux encore, créez les valeurs aléatoires dans le bloc statique d'initialisation en utilisant les outils Java disponibles. Et si vous avez besoin répétables nombres « aléatoires », alors que l'instance de semences Random avec un fixe, mais au hasard nombre CHOISI chaque fois.

Outre les valeurs des nombres entiers, le constructeur et l'initialiseur doit contenir les instructions JVM pour le chargement des entiers dans le tableau.

Une approche beaucoup plus simple et plus pratique est de stocker les numéros dans un fichier, que ce soit dans un format binaire ou sous forme de texte.

Je ne sais pas ce que java initialisés tableaux de cette façon, mais il n'a pas d'initialiser de grands tableaux efficacement.

Je pense que la taille du code en caractères est plus que 65535. pas la mémoire utilisée par 10000 entiers.

Je pense qu'il est possible que ce soit la quantité de mémoire nécessaire pour représenter ces ints alphanumériquement. Je pense que cette limite pourrait demander le code lui-même, donc, chaque int, par exemple:. 1494512072 prend en fait 10 octets (un par chiffre) au lieu de seulement 4 octets utilisés pour la int32

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top