9

免责声明:我意识到我可以在运行时在 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
4

6 回答 6

14

以下是使用 {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 个元素,您必须期望大约 80kB 的字节码。

用 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]
于 2009-04-25T12:53:34.377 回答
6

数组字面量被翻译成用值填充数组的字节码,因此每个数字需要更多字节。

为什么不将该数据移出到您在类加载时加载的静态初始化程序块中的资源中呢?这可以通过使用轻松完成MyClass.class.getClassLoader().getResourceAsStream()。无论如何,这似乎是它所属的地方。

或者更好的是,使用可用的 Java 工具在静态初始化程序块中创建随机值。如果您需要可重复的“随机”数字,那么只需Random每次使用固定但随机选择的数字为实例播种。

于 2009-04-25T12:28:03.580 回答
3

除了整数的值之外,构造函数和初始化程序还需要包含用于将整数加载到数组中的 JVM 指令。

于 2009-04-25T12:19:52.803 回答
1

一种更简单、更实用的方法是将数字以二进制格式或文本形式存储在文件中。

我不知道什么 java 以这种方式初始化数组,但它不能有效地初始化大型数组。

于 2009-04-25T15:28:32.943 回答
0

我认为字符的代码大小超过 65535。不是 10000 个整数占用的内存。

于 2009-04-25T12:18:48.407 回答
-5

我认为这可能是用字母数字表示这些整数所需的内存量。我认为这个限制可能适用于代码本身,因此,每个 int,例如:1494512072 实际上需要 10 个字节(每个数字一个),而不是仅用于 int32 的 4 个字节。

于 2009-04-25T12:15:44.420 回答