我已尝试过各种代码将大型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>
我无法找到解决此问题的方法。有人可以帮我解决这个问题吗?任何帮助都将非常感激。
答案 0 :(得分:1)
加载到字节数组中时,300MB的文件不会消耗6GB的堆。仔细观察堆栈跟踪,看起来加载部分完全没问题。 " java.lang.OutOfMemoryError:Java堆空间"只有在尝试使用Log4j记录某些内容时才会抛出。
日志记录似乎来自第三方代码而不是您自己的代码,因此您可能无法更改记录的内容,但您肯定可以通过Log4j配置减少日志记录,尝试增加日志级别(到WARN, org.apache。*的错误或致命)你应该好好去。