执行"文件到字​​节[]"时出现OutOfMemoryError错误在Java中的大文件?

时间:2014-08-19 23:07:45

标签: java file bytearray heap space

我已尝试过各种代码将大型CSV文件(~300 MB)转换为byte [],但每次都无法提供Java堆空间错误,如下所示:

  

184898 [jobLauncherTaskExecutor-1] DEBUG   org.springframework.batch.core.step.tasklet.TaskletStep - 回滚   for Error:java.lang.OutOfMemoryError:Java堆空间185000   [jobLauncherTaskExecutor-1] DEBUG   org.springframework.transaction.support.TransactionTemplate -   在应用程序异常上启动事务回滚   java.lang.OutOfMemoryError:Java堆空间           at java.util.Arrays.copyOf(Arrays.java:2367)           at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130)           at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114)           在java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:415)           在java.lang.StringBuffer.append(StringBuffer.java:237)           在org.apache.log4j.helpers.PatternParser $ LiteralPatternConverter.format(PatternParser.java:419)           在org.apache.log4j.PatternLayout.format(PatternLayout.java:506)           在org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:310)           在org.apache.log4j.WriterAppender.append(WriterAppender.java:162)           在org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)           在org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)           在org.apache.log4j.Category.callAppenders(Category.java:206)           在org.apache.log4j.Category.forcedLog(Category.java:391)           在org.apache.log4j.Category.log(Category.java:856)           在org.slf4j.impl.Log4jLoggerAdapter.log(Log4jLoggerAdapter.java:601)           在org.apache.commons.logging.impl.SLF4JLocationAwareLog.debug(SLF4JLocationAwareLog.java:133)           在org.apache.http.impl.conn.Wire.wire(Wire.java:77)           在org.apache.http.impl.conn.Wire.output(Wire.java:107)           at org.apache.http.impl.conn.LoggingSessionOutputBuffer.write(LoggingSessionOutputBuffer.java:76)           at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:119)           在org.apache.http.entity.ByteArrayEntity.writeTo(ByteArrayEntity.java:115)           在org.apache.http.entity.HttpEntityWrapper.writeTo(HttpEntityWrapper.java:98)           at org.apache.http.impl.client.EntityEnclosingRequestWrapper $ EntityWrapper.writeTo(EntityEnclosingRequestWrapper.java:108)           在org.apache.http.impl.entity.EntitySerializer.serialize(EntitySerializer.java:122)           at org.apache.http.impl.AbstractHttpClientConnection.sendRequestEntity(AbstractHttpClientConnection.java:271)           at org.apache.http.impl.conn.AbstractClientConnAdapter.sendRequestEntity(AbstractClientConnAdapter.java:227)           at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:257)           在org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)           at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:712)           在org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:517)           at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)           在org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)

到目前为止,我已尝试使用以下版本的代码来执行byte[]转换文件:

版本1:核心Java

    File file = new File(fileName);
    FileInputStream fin = null;
    byte fileContent[] = null;

    try {
        fin = new FileInputStream(file);

        fileContent = new byte[(int) file.length()];

        fin.read(fileContent);

    } catch (FileNotFoundException e) {
        System.out.println("File not found" + e);
    } catch (IOException ioe) {
        System.out.println("Exception while reading file " + ioe);
    } finally {
        try {
            if (fin != null) {
                fin.close();
            }
        } catch (IOException ioe) {
            System.out.println("Error while closing stream: " + ioe);
        }
    }

    return fileContent;

版本2:Java 7 NIO

    Path path = Paths.get(fileName);

    byte[] data = null;

    try {
        data = Files.readAllBytes(path);
    } catch (IOException e) {
        e.printStackTrace();
    }

    return data;

版本3:Apache Commons IO

    File file = new File(fileName);
    FileInputStream fis = null;
    byte fileContent[] = null;

    try {
        fis = new FileInputStream(file);

        fileContent = IOUtils.toByteArray(fis);

    } catch (FileNotFoundException e) {
        System.out.println("File not found" + e);
    } catch (IOException ioe) {
        System.out.println("Exception while reading file " + ioe);
    } finally {
        try {
            if (fis != null) {
                fis.close();
            }
        } catch (IOException ioe) {
            System.out.println("Error while closing stream: " + ioe);
        }
    }

    return fileContent;

版本4:Google Guava

    File file = new File(fileName);
    FileInputStream fis = null;
    byte fileContent[] = null;

    try {
        fis = new FileInputStream(file);

        fileContent = ByteStreams.toByteArray(fis);

    } catch (FileNotFoundException e) {
        System.out.println("File not found" + e);
    } catch (IOException ioe) {
        System.out.println("Exception while reading file " + ioe);
    } finally {
        try {
            if (fis != null) {
                fis.close();
            }
        } catch (IOException ioe) {
            System.out.println("Error while closing stream: " + ioe);
        }
    }

    return fileContent;

第5版:Apache.commons.io.FileUtils

File file = new File(fileName);

byte fileContent[] = null;

try {

    fileContent =  org.apache.commons.io.FileUtils.readFileToByteArray(file);

} catch (FileNotFoundException e) {
    System.out.println("File not found" + e);
} catch (IOException ioe) {
    System.out.println("Exception while reading file " + ioe);
}

return fileContent;

我甚至设置了我的堆空间设置非常大。我的外部Tomcat大约为6 GB(5,617,772 K),如任务管理器中的内存消耗所示。

对于前三个版本的代码,在按下此byte []生成代码时,堆空间突然增加到超过5 GB,然后失败。使用Google Guava,看起来非常有前景,内存消耗在相当长的时间内保持在3.5 GB左右,比如大约10分钟,在点击byte []生成代码之后,它突然跳到超过5 GB并且失败了。 / p>

我无法找到解决此问题的方法。有人可以帮我解决这个问题吗?任何帮助都将非常感激。

1 个答案:

答案 0 :(得分:1)

加载到字节数组中时,300MB的文件不会消耗6GB的堆。仔细观察堆栈跟踪,看起来加载部分完全没问题。 " java.lang.OutOfMemoryError:Java堆空间"只有在尝试使用Log4j记录某些内容时才会抛出。

日志记录似乎来自第三方代码而不是您自己的代码,因此您可能无法更改记录的内容,但您肯定可以通过Log4j配置减少日志记录,尝试增加日志级别(到WARN, org.apache。*的错误或致命)你应该好好去。