当前位置: 首页 > 知识库问答 >
问题:

Java 中字节数组的内存使用情况 [重复]

岑俊弼
2023-03-14

对于启发式预计算表,我需要一个包含1504935936个条目的字节数组。这大约需要1.5 GB内存。

public class Main{
    public static void main(String[] args){
        byte[] arr = new byte[1504935936];
    }
}

为什么我有一个“内存不足错误:Java堆空间”-例外,如果我给程序2 GB的RAM

java -Xmx2048M Main

java -Xmx2153M Main

它起作用了。为什么它需要那么多RAM?

共有3个答案

仲鸿风
2023-03-14

如果进程作为32位进程执行,大多数操作系统只为进程保留大约2GB的地址空间,另外2GB的地址空间映射为内核内容(因此,当您的进程调用内核内容时,您不必执行那么多上下文切换)。

即使您的机器有8gb的ram,或2GB的交换空间,每个32位进程也只能分配和寻址2GB,除非您使用PAE或类似的。

这会导致一些问题。第一,您可能没有足够的原始地址空间来存储所有分配的总大小。第二,您可能没有一个与您需要的数组大小相同的连续内存块——Java和其他几个VM环境使用单独的堆来存储不同类型的内存,例如,与第0代或第1代等对象分开的大型对象堆。每个分区都会导致较小的连续区域。

在64位进程中,地址空间限制几乎消失了,但是,您可能仍然没有足够的连续的、可提交的、java允许的内存来满足请求。如果您将Java设置为只允许2GB的内存,您可能仍然难以找到足够的连续内存来满足请求

请记住,该进程确实需要相当大的内存来存储程序的代码页,并且需要java运行时的内存。仅这一点就可能是几百兆内存,这取决于程序其余部分的需求。

在分配 1 元素字节数组的同时执行简单程序,并使用 SysInternal 的 VMMap 检查内存以了解内存开销的来源(不包括大量分配),这可能很有启发性。

然后用你的大笔拨款试一试,看看你会得到什么。

毋弘光
2023-03-14

这里的其他帖子有一些很好的信息,但是他们错过了一个关键点:

找一个好的内存分析器(最好是带视觉显示的),并将其附加到jvm上。您将看到的是,现代jvm没有一个大的堆空间,而是有多个池(也称为世代)。通常,“旧世代”是最大的,但您也会有其他几个池。所有这些池加起来应该大致相当于您允许jvm使用的堆空间。

因此,您的“-Xmx2048M”设置不会产生具有单个池的堆,该池可以支持1.5GB阵列(正如其他人所指出的,您需要为阵列提供单个连续的内存块,即完全包含在单个池/代中的内存块)。

麹飞航
2023-03-14

可能是因为程序中的其他数据正在使用和分割Java堆。

该字节数组需要作为Java堆空间中一个连续的1.5GB内存块进行分配。(Java语言规范不要求这样做,但AFAIK是所有当前JVM实现的实际工作方式。)您的一些堆空间正在被消耗,而且可能更重要的是,在分配大字节数组之前,程序中发生的其他内存分配会将其分割。java-Xmx2153M Main可能是您必须使整个堆有多大,才能在分配时留下连续的1.5 GB空间。

如果将该大数组切成 100 个大小为 1/100 的较小数组,则它可能适合较小的堆,因为它对堆碎片不那么敏感。

 类似资料:
  • 问题内容: 是否有一个准则来估计a消耗的内存量? 寻找类似于这些准则的估计内存使用情况的东西。 问题答案: 如果您查看源代码中的字段,则有: 的评论说 用于存储规范的字符串表示形式(如果已计算)。 假设您不调用,它将保留为零字节。因此是(8 + 4 + 4)= 16个字节+ 。 本身是4 + 4 + 4 + 4 + 4 = 20字节+ 。 20 + 16总共提供了36个字节加上大小,该大小始终是表

  • 问题内容: 扩展基类时,Java中的内存使用情况如何。 子类是否包含基类的实例(具有其自身的开销和全部开销),还是仅具有其自身的16字节的开销? 那么,更具体地说,Bar实例的内存使用量是多少? 是吗 要不就 问题答案: 没有双重开销。 Java将采用该类,超类,计算所有字段所需的空间,并为一个实例分配所需的空间。 仅从内存的角度来看,根本不存在超类的概念,有Foo的实例仅需要一个int的内存,而

  • 问题内容: 我正在使用 map [string] string 优化代码,其中 map 的值仅为“ A”或“ B”。因此,我认为显然, map [string] bool 更好,因为该地图可容纳约5000万个元素。 结果是: 在测试时,我发现有些奇怪,为什么带有很长字符串的 a2 使用8个字节,就像 一个 只有一个字母一样? 问题答案: 不会递归地进入数据结构,它只是报告传递的值的“浅”大小。引用

  • 问题内容: 有什么工具可以知道我的Java应用程序已使用了多少个本机内存?我的应用程序内存不足:当前设置是:-Xmx900m 计算机,Windows 2003 Server 32位,RAM 4GB。 还在Windows上将boot.ini更改为/ 3GB,会有什么不同吗?如果设置为Xmx900m,则可以为此进程分配多少最大本机内存?是1100m吗? 问题答案: (就我而言,我使用的是Java 8)

  • 问题内容: 我有大量的名称-值对(大约100k),我需要将它们存储在某种高速缓存(例如哈希映射)中,其中值是一个平均大小约为30k字节的字符串。 现在我知道一个事实,大量的值具有完全相同的字符串数据。为了避免多次分配相同的字符串数据,我想以某种方式重用以前分配的字符串,从而减少内存消耗。另外,这需要相当快。即,不能一一扫描所有先前分配的值。 关于如何解决此问题的任何建议? 问题答案: 千万 不能

  • 问题内容: 我正在尝试跟踪处理URL的脚本的内存使用情况。基本思想是在将另一个URL添加到cURL多处理程序之前,检查是否存在合理的缓冲区。我正在使用“滚动cURL”概念,该概念在多处理程序运行时处理URL数据。这意味着我可以在每次处理和删除现有URL时通过从池中添加新URL来保持N个连接处于活动状态。 我已经使用了一些积极的结果。添加该标志很有帮助(虽然并不清楚“系统”内存和“ emalloc”