int[] 和 Integer[] 数组的内存占用

发布于 2024-11-09 12:55:42 字数 463 浏览 5 评论 0原文

我尝试创建一个整数数组(我尝试使用自己的对象,但 int 也发生了同样的情况),大小为 3000 万。我不断收到“OutOfMemoryError:Java堆空间”

Integer [] index = new Integer[30000000];
for (int i = 0 ; i < 30000000 ; i++){
    index[i] = i;
}

我使用“Runtime.getRuntime().totalMemory()”和“maxMemory()”检查了总堆空间 看到我从 64 MB 开始,最大值为 900+ MB,在运行过程中,我的堆和压碎达到 900+ MB。

现在我知道 Integer 需要 4 个字节,所以即使我乘以 30*4*1000000 我仍然只能得到大约 150-100 兆。

如果我尝试使用原始类型,例如 int,它会起作用。

我该如何解决它?

I try to create an array of Integers (i tried with own object but the same happened with int) , with size of 30 million. i keep getting "OutOfMemoryError: Java heap space"

Integer [] index = new Integer[30000000];
for (int i = 0 ; i < 30000000 ; i++){
    index[i] = i;
}

i checked the total heap space, using "Runtime.getRuntime().totalMemory()" and "maxMemory()"
and saw that i start with 64 MB and the max is 900+ MB, and during the run i get to 900+ on the heap and crush.

now i know that Integer takes 4 bytes, so even if i multiply 30*4*1000000 i should still only get about 150-100 mega.

if i try with a primitive type, like int, it works.

how could i fix it ?

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

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

发布评论

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

评论(5

杀手六號 2024-11-16 12:55:42

Java 的 int 原语将占用 4 个字节,但如果您使用像 Integer 这样的 ValueObject,它将占用更多空间。根据您的机器,单独的引用可能占用 32 或 64 位+它所包装的原语的大小。

如果空间是个问题,您可能应该只使用原始整数。

Java's int primitive will take up 4 bytes but if you use a ValueObject like Integer it's going to take up much more space. Depending on your machine a reference alone could take up 32 or 64 bits + the size of the primitive it is wrapping.

You should probably just use primitive ints if space is an issue. Here is a very good SO answer that explains this topic in more detail.

盛夏已如深秋| 2024-11-16 12:55:42

假设我们正在讨论基于 OpenJDK 的 32 位 JVM。

  • 每个 Integer 对象都有 1 个 int 字段 - 占用 4 个字节。
  • 每个 Integer 对象有 2 个头字 - 占用 8 个字节。
  • 分配的粒度(我认为)是 2 个字 - 4 个字节的填充。
  • Integer[] 对每个数组元素/位置有 1 个引用 - 4 个字节。

因此每个数组元素总计 20 个字节。 20 x 30 x 1,000,000 = 600,000,000 兆字节。现在添加一个事实,即分代收集器将分配至少 3 个不同大小的对象空间,并且可以轻松添加到 900+ MB。


我该如何解决它?

  • 使用 int[] 而不是 Integer
  • 如果 Integer 值主要表示 -128 到 + 127 范围内的数字,请使用 Integer.valueOf(int) 分配它们。 JLS 保证以这种方式创建的Integer 对象将被共享。 (请注意,当通过自动装箱创建 Integer 时,JLS 规定使用 valueOf。因此,事实上,此“修复”已应用在您的例如。)
  • 如果您的 Integer 值主要来自较大但仍然较小的域,请考虑实现您自己的缓存以共享 Integer 对象。

我的问题是以 Integer 为例,在我的程序中,我使用自己的对象,该对象仅保存字节数组(最大大小为 4)。当我创建它时,它占用的内存远远超过 4 个字节。

是的,会的。

假设您的类定义如下:

public class MyInt {
    private byte[] bytes = new byte[4];
}

每个 MyInt 将占用:

  • MyInt 标头字 - 8 字节
  • MyInt.bytes 字段 - 4 字节
  • 填充 - 4 字节
  • 字节数组的标头字 - 12 字节
  • 数组内容 - 4 字节

现在添加 MyInt 引用占用的空间:

  • 对每个 MyInt 的引用 - 4 字节

总计- MyInt[] 的每个 MyInt 元素 36 个字节。

Integer[] 的每个 Integer 元素 20 个字节或 int[] 的每个 int 元素 4 个字节进行比较代码>.


如何解决这个问题?

一个 4 字节的数组包含 32 位数据。可以将其编码为int。所以修复方法与之前相同。使用 int[] 而不是 MyInt[],或者(可能)采用上面讨论的其他想法之一。

或者,增大堆,或者使用数据库或类似的东西,这样数据就不需要保存在 RAM 中。

Lets assume that we are talking about a 32bit OpenJDK-based JVM.

  • Each Integer object has 1 int field - occupying 4 bytes.
  • Each Integer object has 2 header words - occupying 8 bytes.
  • The granularity of allocation is (I believe) 2 words - 4 bytes of padding.
  • The Integer[] has 1 reference for each array element / position - 4 bytes.

So the total is 20 bytes per array element. 20 x 30 x 1,000,000 = 600,000,000 Mbytes. Now add the fact that the generational collector will allocate at least 3 object spaces of various sizes, and that could easily add up to 900+ Mbytes.


how could i fix it ?

  • Use int[] instead of Integer.
  • If the Integer values mostly represent numbers in the range -128 to + 127, allocate them with Integer.valueOf(int). The JLS guarantees that Integer objects created that way will be shared. (Note that when an Integer is created by auto-boxing, then JLS stipulates that valueOf is used. So, in fact, this "fix" has already been applied in your example.)
  • If your Integer values mostly come from a larger but still small domain, consider implementing your own cache for sharing Integer objects.

My question was about Integer as an example, in my program i use my own object that only holds an array of bytes (max size of 4). when i create it, it takes a lot more then 4 bytes on the memory.

Yes, it will do.

Let's assume your class is defined like this:

public class MyInt {
    private byte[] bytes = new byte[4];
}

Each MyInt will occupy:

  • MyInt header words - 8 bytes
  • MyInt.bytes field - 4 byte
  • Padding - 4 bytes
  • Header words for the byte array - 12 bytes
  • Array content - 4 bytes

Now add the space taken by the MyInt reference:

  • Reference to each MyInt - 4 bytes

Grand total - 36 bytes per MyInt element of a MyInt[].

Compare that with 20 bytes per Integer element of an Integer[] or 4 bytes per int element of an int[].


How to fix that case?

Well an array of 4 bytes contains 32 bits of data. That can be encoded as int. So the fix is the same as before. Use an int[] instead of a MyInt[], or (possibly) adapt one of the other ideas discussed above.

Alternatively, make the heap larger, or use a database or something like that so that the data doesn't need to be held in RAM.

彩虹直至黑白 2024-11-16 12:55:42

Integer 是一个占用超过 4 个字节的对象。还有多少取决于实施。你真的需要Integer吗?唯一的好处是它可以为 null。也许你可以使用“哨兵值”来代替;例如,-1 或 Integer.MIN_VALUE

Integer is an object which will take more than 4 bytes. How much more is implementation dependent. Do you really need Integer? The only benefit is that it can be null. Perhaps you could use a "sentinal value" instead; say, -1, or Integer.MIN_VALUE.

强辩 2024-11-16 12:55:42

也许您应该使用数据库而不是大型数组,但如果您必须使用大型对象数组,您是否尝试在运行 Java 应用程序启动器时使用 -Xms 命令行参数来增加 Java 内存大小?

Perhaps you should be using a database rather than a huge array, but if you must use a huge array of objects, have you tried increasing the Java memory size by using a the -Xms command line argument when running the Java application launcher?

只为守护你 2024-11-16 12:55:42

这不是您想要的,但最佳解决方案是在这个简单的示例中使用函数而不是数组。

static int index(int num) {
    return num;
}

如果您有更现实的示例,可能还可以使用其他优化。

This is not what you are looking for but the optimal solution is to use a function instead of an array in this simple example.

static int index(int num) {
    return num;
}

If you have a more realistic example, there may be other optimisations you can use.

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