Por não exceder o 65.535 bytes limite em Java construtores e Inicializadores estáticos?

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

  •  16-09-2019
  •  | 
  •  

Pergunta

Isenção de responsabilidade:Eu percebo que pode gerar isso em tempo de execução em Java, isso foi necessário para que um caso muito especial, enquanto os testes de desempenho de algum código.Eu encontrei uma abordagem diferente, agora isso é só mais uma curiosidade do que qualquer coisa prática.

Eu tentei o seguinte como um campo estático, como um campo de instância, e inicializado diretamente no construtor.Cada vez que o eclipse está me informando que "O código do construtor TestData() é superior a 65535 bytes limite" ou "o código para O inicializador estático é superior a 65535 bytes limite".

Há 10.000 números inteiros.Se cada um int é de 4 bytes (32bits), então isso não seria de 40.000 bytes?Há muito mais que 25,0000 bytes de sobrecarga, além dos dados apenas se limita a construção da matriz?

Os dados são gerados com este pouco 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 "};";

Aqui está uma pequena amostra:

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
Foi útil?

Solução

Aqui está o bytecode para inicializar uma matriz com {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]

Portanto, para esta pequena matriz, cada elemento requer 5 bytes de bytecode java. Para sua matriz maior, o índice da matriz e o índice no pool constante usarão 3 bytes para a maioria dos elementos, o que leva a 8 bytes por elemento da matriz. Portanto, para 10000 elementos, você esperaria cerca de 80kb de código de bytes.

O código para inicializar grandes matrizes com índices de 16 bits se parece com o seguinte:

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

Outras dicas

Os literais da matriz são traduzidos para o código de bytes que preenche a matriz com os valores, para que você precise de mais alguns bytes para cada número.

Por que não mover esses dados para um recurso que você carrega no tempo de carregamento da aula em um bloco inicializador estático? Isso pode ser feito facilmente usando MyClass.class.getClassLoader().getResourceAsStream(). Parece que isso pertence, de qualquer maneira.

Ou melhor ainda, crie os valores aleatórios no bloco inicializador estático usando as ferramentas Java disponíveis. E se você precisar de números "aleatórios" repetíveis, basta semear o Random instância com um número fixo, mas aleatoriamente, a cada vez.

Além dos valores dos números inteiros, o construtor e o inicializador precisam conter as instruções da JVM para carregar os números inteiros na matriz.

Uma abordagem muito mais simples e prática é armazenar os números em um arquivo, em um formato binário ou como texto.

Não sei o que o Java inicializa as matrizes dessa maneira, mas não inicializa grandes matrizes com eficiência.

Eu acho que o tamanho do código nos caracteres é superior a 65535. Não é a memória tirada por 10000 inteiros.

Eu acho que é possível que essa é a quantidade de memória necessária para representar os ints alfanumericamente.Eu acho que esse limite poderá aplicar para o código propriamente dito, então, cada um int, por exemplo:1494512072, na verdade, leva de 10 bytes ( uma por dígitos ) em vez de apenas 4 bytes usados para int32.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top