Почему это превышает предел 65,535 байтов в конструкторах Java и статических Инициализаторах?

отказ от ответственности: я понимаю, что могу создать это во время выполнения на Java, это было необходимо для очень особого случая при тестировании производительности некоторого кода. Я нашел другой подход, так что теперь это скорее любопытство, чем что-либо практическое.

Я пробовал следующие, как статическое поле, как поле экземпляра и инициализации в конструктор. Каждый раз, когда eclipse сообщает мне, что либо "код конструктора TestData () превышает Ограничение 65535 байт"или" код для статического инициализатора превышает ограничение 65535 байт".

есть 10 000 целых чисел. Если каждый int равен 4 байтам (32 бит), то не будет ли это 40 000 байтов? Есть ли на самом деле больше, чем 25,0000 байтов накладных расходов в дополнение к данным, просто просто создающим массив?

данные генерируются с помощью этого небольшого бита 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 "};";

вот небольшой пример:

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

6 ответов


вот код для инициализации массива с {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]

поэтому для этого небольшого массива каждый элемент требует 5 байтов байт-кода Java. Для вашего большего массива как индекс массива, так и индекс в пуле констант будут использовать 3 байта для большинства элементов, что приводит к 8 байтам на элемент массива. Таким образом, для 10000 элементов вам придется ожидать около 80 КБ байтового кода.

код для инициализации больших массивов с 16-битными индексами выглядит вот так:

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

литералы массива преобразуются в байтовый код, который заполняет массив значениями, поэтому вам нужно еще несколько байтов для каждого числа.

почему бы не переместить эти данные в ресурс, который вы загружаете во время загрузки класса в статическом блоке инициализатора? Это можно легко сделать с помощью MyClass.class.getClassLoader().getResourceAsStream(). Кажется, это оно там, где ему и место.

или еще лучше, создайте случайные значения в статическом блоке инициализатора, используя доступные инструменты Java. И если тебе нужно ... повторяемые "случайные" числа, а затем просто семя Random экземпляр с фиксированным, но случайным образом выбранные числа каждый раз.


помимо значений целых чисел, конструктор и инициализатор должны содержать инструкции JVM для загрузки целых чисел в массив.


гораздо проще и практичнее хранить числа в файле, либо в двоичном формате, либо в виде текста.

Я не знаю, что java инициализирует массивы таким образом, но он не инициализирует большие массивы эффективно.


Я думаю, что размер кода в символах больше, чем 65535. Не память на 10000 чисел.


Я думаю, что возможно, что это объем памяти, необходимый для представления этих ints буквенно-цифровым способом. Я думаю, что это ограничение может применяться для самого кода, поэтому каждый int, например: 1494512072 фактически занимает 10 байтов (по одному на цифру ) вместо только 4 байтов, используемых для int32.