为什么这超出了 Java 构造函数和静态初始化程序中的 65,535 字节限制?

发布于 2024-07-18 10:04:40 字数 1811 浏览 2 评论 0原文

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

Disclaimer: I realize I can generate this at runtime in Java, this was needed for a very special case while performance testing some code. I've found a different approach, so now this is just more of a curiosity than anything practical.

I've tried the following as a static field, as an instance field, and initialized directly within the constructor. Every time eclipse is informing me that either "The code of constructor TestData() is exceeding the 65535 bytes limit" or "The code for the static initializer is exceeding the 65535 bytes limit".

There are 10,000 integers. If each int is 4 bytes (32bits), then would that not be 40,000 bytes? Is there really more that 25,0000 bytes of overhead in addition to the data just merely constructing the array?

The data is generated with this small bit of 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 "};";

Here's a small sample:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

咽泪装欢 2024-07-25 10:04:41

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

I think that code size in characters is more than 65535. Not the memory taken by 10000 integers.

因为看清所以看轻 2024-07-25 10:04:41

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

I think it's possible that this is the amount of memory required to represent those ints alphanumerically. I think this limit might apply for the code itself, so, each int, for instance: 1494512072 actually takes 10 bytes ( one per digit ) instead of only 4 bytes used for the int32.

我们的影子 2024-07-25 10:04:40

下面是用 {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]

Here is the bytecode for initializing an array with {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]

So for this small array each element requires 5 bytes of Java bytecode. For your bigger array both the array index and the index into the constant pool will use 3 bytes for most elements, which leads to 8 bytes per array element. So for 10000 elements you'd have to expect about 80kB of byte code.

The code for initializing big arrays with 16 bit indices looks like this:

2016  dup
2017  sipush 298
2020  ldc_w <Integer 100298> [310]
2023  iastore
2024  dup
2025  sipush 299
2028  ldc_w <Integer 100299> [311]
青春如此纠结 2024-07-25 10:04:40

数组文字被转换为用值填充数组的字节代码,因此每个数字都需要更多字节。

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

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

Array literals are translated into the byte code that fills the array with the values, so you need a few more bytes for each number.

Why not move that data out into a resource that you load at class-loading time in a static initializer block? This can easily be done by using MyClass.class.getClassLoader().getResourceAsStream(). It seems that this it where it belongs, anyway.

Or better yet, create the random values in the static initializer block using the Java tools available. And if you need repeatable "random" numbers, then just seed the Random instance with a fixed, but randomly choosen number each time.

八巷 2024-07-25 10:04:40

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

Besides the values of the integers, the constructor and the initializer needs to contain the JVM instructions for loading the integers into the array.

浅唱々樱花落 2024-07-25 10:04:40

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

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

A much simpler and more practical approach is to store the numbers in a file, either in a binary format or as text.

I don't know what java initialises arrays this way, but it does not initialise large arrays efficiently.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文