Почему это превышает ограничение в 65 535 байт в конструкторах Java и статических инициализаторах? - PullRequest
9 голосов
/ 25 апреля 2009

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

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

Есть 10000 целых чисел. Если каждое int равно 4 байта (32 бита), то не будет ли это 40000 байтов? Действительно ли в дополнение к данным только 250000 байтов служебных данных просто строят массив?

Данные генерируются с помощью этого маленького кусочка 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 ]

13 голосов
/ 25 апреля 2009

Вот байт-код для инициализации массива с {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]
6 голосов
/ 25 апреля 2009

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

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

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

3 голосов
/ 25 апреля 2009

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

1 голос
/ 25 апреля 2009

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

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

0 голосов
/ 25 апреля 2009

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

0 голосов
/ 25 апреля 2009

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

...