【问题标题】:Multidimension array in java inefficiant memory allocationjava中的多维数组内存分配不足
【发布时间】:2015-12-29 06:41:52
【问题描述】:

如果堆足够大以创建最外层数组,则分配 1 个多维数组的简单程序会导致连续 GC(所有垃圾收集器)。似乎GC尝试了很多次。使用产品构建和 6G 堆,分配需要 3 分钟。

使用快速调试构建,分配需要 20 多分钟。

分配占用相同内存的一维数组速度很快,并且不会抛出任何内存异常为什么?

    public class Test {
    public static void main(String[] args) {
            int a1 = 1;
            long maxMemory = Runtime.getRuntime().maxMemory();
            int s = (int) (Math.sqrt(Math.sqrt((double) maxMemory)));
            System.out.println("s: " + s);
            int[][][][] a2;
    try {
        a2 = new int [s][s][s][s];
        a2 [s-1][s-1][s-1][s-1] = a1;
        if ( a2 [s-1][s-1][s-1][s-1] != 1 ) {
            throw new RuntimeException("Error: " + a2 [s-1][s-1][s-1][s-1]);
        }
    } catch (OutOfMemoryError e) {
            System.out.println("Passed.");
    }
    }
}

【问题讨论】:

    标签: java arrays memory-management


    【解决方案1】:

    我看到的第一个问题是您正在计算最大堆大小而不是最大 可用 堆大小:您需要考虑已经分配的内容。例如:

    Runtime rt = Runtime.getRuntime();
    long availableMemory = rt.maxMemory() - (rt.totalMemory() - rt.freeMemory());
    

    第二个问题是您试图创建与最大堆大小(以字节为单位)一样多的int 值。由于 int 用 4 个字节表示,因此您尝试分配的内存是最大堆大小的 4 倍,这应该总是抛出 OOME。因此,大小s应重新计算为:

    int s = (int) (Math.sqrt(Math.sqrt((double) availableMemory))) / 4;
    

    最后,根据数组的多维性,您不仅要分配 int 值,还要引用 int[]int[][]int[][][]。所以实际的最大数组大小应该针对这些引用的分配进行调整。如果我没记错的话,这相当于解决(或找到一个很好的近似)这个方程:

    availableMem >= s * refSize + s^2 *refSize + s^3 * refSize + s^4 * 4
    

    其中 refSize 是 JVM 中引用表示的大小,可能取决于平台(例如 32 位 JVM 为 4 个字节,64 位为 8 个字节)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-15
      • 2012-10-07
      • 2015-06-08
      • 1970-01-01
      • 2012-02-05
      • 1970-01-01
      • 1970-01-01
      • 2015-02-01
      相关资源
      最近更新 更多