内存不足错误,java堆空间

Ari*_*man 5 java heap-memory

我尝试读取超过400万行和超过400 MB的日志文件,但我得到Out of Memory Error:java堆空间.这是我的代码:

File file = new File("C:\\file.log");
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        StringBuilder stringBuffer = new StringBuilder();
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            stringBuffer.append(line);
        }
Run Code Online (Sandbox Code Playgroud)

我试图将堆内存增加到1GB,但仍然得到该消息.可能的原因是什么?

See*_*ose 20

好的,你已经有了线索,阅读你得到的评论.

问题解释:

您的日志文件大小为400MB.请注意,这是以字节为单位.现在,您逐行读取它,line = bufferedReader.readLine()从而将一些字节转换为字符串.

StringJava中的一个实例内部拥有一个char[].但charJava中需要2个字节!所以你需要至少800MB的堆空间来存储所有的字符.由于您还要分配其他几个对象,并且JVM本身需要一些内存,因此很可能1 GB是不够的.

此外,StringBuffer(顺便说一句:更好地使用StringBuilder)内部再次使用a char[],在需要时自动扩展(长度).这种扩展是通过加倍长度来完成的.因此,对于400MB的文件,它char[]的长度为512M.仍然提醒:一个字符需要2个字节.

那么解决方案是什么?简单地说:不要将整个文件读入内存!

这样做:

class LogAnalyzer {
    private final File logFile;

    LogAnalyzer(File logFile) {
        this.logFile = logFile;
    }

    void analyze() throws IOException {
        try(FileReader fileReader = new FileReader(logFile)) {
            try(BufferedReader bufferedReader = new BufferedReader(fileReader)) {
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    analyzeLine(line);
                }
            }
        }
    }

    private void analyzeLine(String line) {
        // do whatever you need here
    }
}
Run Code Online (Sandbox Code Playgroud)

如果需要保留一些行,则应将它们存储在LogAnalyzer的某些实例字段中,和/或使此类的行为类似于状态机.