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