【问题标题】:Using too much Ram in Java在 Java 中使用过多的 Ram
【发布时间】:2013-01-20 20:09:07
【问题描述】:

我正在用java编写一个程序,它必须使用一个大的哈希表,哈希表越大越好(这是一个国际象棋程序:P)。基本上,作为哈希表的一部分,我有一个“long[]”数组、一个“short[]”数组和两个“byte[]”数组。所有这些都应该是相同的大小。但是,当我将表大小设置为一千万时,它崩溃并显示“java heap out of memory”。这对我来说毫无意义。这是我的看法:

1 Long + 1 Short + 2 Bytes = 12 bytes
x 10,000,000 = 120,000,000 bytes
/ 1024 = 117187.5 kB
/ 1024 = 114.4 Mb

现在,114 Mb 的 RAM 对我来说似乎并不算多。我的 CPU 在我的 Mac 上总共有 4Gb 的 RAM,我有一个名为 FreeMemory 的应用程序,它显示了我有多少可用的 RAM,并且在运行这个程序时它大约是 2Gb。此外,我设置了 java 首选项,如 -Xmx1024m,因此 java 应该能够使用最多内存。那么为什么不让我只分配 114Mb 呢?

【问题讨论】:

  • 您可以使用内存分析器来查看到底发生了什么。
  • 你能试试小一点的吗?排除它可能是一些很棒的递归。
  • 你能想出一个你认为占用太多空间的最小的独立示例,并将它与你正在使用的确切的java 命令行一起发布吗?
  • 哦,顺便说一下,如果我用九百万的大小试试,效果很好。
  • 发布可以重现您的问题的代码,自行分析您的记忆。

标签: java arrays memory ram


【解决方案1】:

您预测它应该使用 114 MB,如果我运行它(在 4 GB 的 windows 机器上)

public static void main(String... args) {
    long used1 = memoryUsed();
    int Hash_TABLE_SIZE = 10000000;
    long[] pos = new long[Hash_TABLE_SIZE];
    short[] vals = new short[Hash_TABLE_SIZE];
    byte[] depths = new byte[Hash_TABLE_SIZE];
    byte[] flags = new byte[Hash_TABLE_SIZE];
    long used2 = memoryUsed() - used1;
    System.out.printf("%,d MB used%n", used2 / 1024 / 1024);
}

private static long memoryUsed() {
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}

打印

114 MB used

我怀疑您正在做其他事情,这是导致您的问题的原因。

我正在使用 Oracle HotSpot Java 7 更新 10

【讨论】:

  • ...就像使用 BlueJ 而不是真正的 JVM。
  • @MattBall 我认为我不需要提供使用的 JVM,但我怀疑你是对的。
  • 过去半小时我一直在忙于研究BlueJ,它的功能集似乎指向了一个建立在JVM之上的JVM。 BlueJ 是用 Java 编写的,但提供了许多类似于动态语言的交互功能,并且无法在使用生产 VM 的专业 IDE 中复制。
【解决方案2】:

没有考虑到每个对象都是一个引用,也使用内存,还有更多“隐藏的东西”......我们还必须考虑对齐......字节并不总是一个字节;-)

要查看实际使用了多少内存,您可以使用分析器:

如果您使用标准 HashMap(或 JDK 中的类似),每个“长”(装箱/拆箱)确实超过 8 个字节),您可以使用它作为基础...(使用更少的内存)

【讨论】:

    【解决方案3】:

    根据我所读到的有关 BlueJ 的信息,几乎不可能找到严肃的技术信息,BlueJ VM 很可能根本不支持原始类型;您的数组实际上是盒装原语。 BlueJ 使用所有 Java 功能的子集,强调面向对象。

    如果是这种情况,再加上考虑到 BlueJ VM 的优先级列表中的性能和效率非常低,您实际上可能使用的内存比您想象的要多得多:整个数量级是完全可以想象的。

    【讨论】:

      【解决方案4】:

      我相信一种方法是在每次执行后清理堆内存,这里有一个链接:

      Java heap space out of memory

      【讨论】:

        猜你喜欢
        • 2019-07-31
        • 1970-01-01
        • 2010-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-21
        • 2022-01-11
        相关资源
        最近更新 更多