“java.lang.OutOfMemoryError:Java 堆空间”与大型二维数组

问题描述 投票:0回答:1

我用Java编写了一个小程序,用于将大文件分割成更小的文件。

代码如下:

import java.io.*;
public class Main {

    final static int DIM = 6;
    final static int GB = 1024 * 1024 * 1024;
    public static void write(char[][] buffer, long currentFile) throws IOException {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("out" + currentFile + ".json"))) {
            long wrote = 0;
            for (int i = 0; i < DIM; i++) {
                int firstNull = GB;
                for(int j = GB - 1; j > 0; j--){
                    if(buffer[i][j] == '\0'){
                        firstNull = j;
                    }
                }
                bw.write(buffer[i], 0, firstNull);
                wrote += firstNull;
            }
            bw.close();
            System.out.println("Wrote " + wrote + " bytes to <out" + currentFile + ".json>");
        }
    }

    public static void main(String[] args) {
        System.out.println("Starting");
        File file = new File("./twd.json");
        long start = System.currentTimeMillis();
        try {
            int bufPos = 0;
            int mapIdx = 0;
            char[][] buffer = new char[DIM][GB];
            long currentFile = 0;
            BufferedReader br = new BufferedReader(new FileReader(file));
            System.out.println("Config correct => Started");
            String line;
            while ((line = br.readLine()) != null){
                if(bufPos + line.length() >= GB){
                    if(mapIdx == DIM - 1){
                        write(buffer, currentFile);
                        buffer = null; // Otherwise it will trigger OutOfMemoryError
                        buffer = new char[DIM][GB];
                        bufPos = 0;
                        double progress = GB * (currentFile + 1.0) /  (file.length() / (double) DIM) * 100;
                        System.out.println("Status: " +  progress + "%");
                        currentFile++;
                        mapIdx = 0;
                    }else{
                        mapIdx++;
                        bufPos = 0;
                        System.out.println("Map idx to " + mapIdx);
                    }
                }
                int i;
                for(i = 0; i < line.length(); i++){
                    buffer[mapIdx][bufPos] = line.charAt(i);
                    bufPos++;
                }
                buffer[mapIdx][bufPos] = '\n';
                bufPos++;
            }
            write(buffer, currentFile);
            long end = System.currentTimeMillis();
            br.close();

            System.out.println("Diff: " + (end - start) / 1000 + "s");
        }catch (IOException e){
            System.out.println("IO Exception");
        }
    }
}

我遇到的问题如下,程序的内存使用量应该是DIM * GB * 2(一个字符是2个字节)GB。当 DIM = 5 时一切正常。如果我尝试增加它,它会抛出该错误。

我尝试传递一个额外的 -Xmx 参数来增加最大堆大小。但没有任何运气。 (我的系统有 48GB RAM,但甚至尝试指定 -Xmx(n)g,其中 n 是一个非常高的数字 (< 40) does not work.)

我注意到,在没有任何附加参数且 DIM = 5 的情况下,任务管理器向我显示该程序已达到 12GB RAM 的使用量。

我错过了什么吗?


当我尝试初始化 char[][] 且 DIM 大于或等于 6 时,会抛出“java.lang.OutOfMemoryError: Java heap space”。
我知道代码可以更有效并且绝对更简单,但我想知道是什么导致程序崩溃以及为什么(我无法弄清楚)而不是仅仅让它工作:)
java heap-memory
1个回答
0
投票

我可以使用 6 以上的 DIM 运行你的程序。根据你的评论,你使用

java Main -Xmx32g

您需要将 VM 参数放在类名之前:

java -Xmx32g Main 
© www.soinside.com 2019 - 2024. All rights reserved.