我刚接触Java,正在读取非常大的文件,需要一些帮助来理解问题并解决它。我们有一些遗留代码,必须进行优化,使其运行properly.The文件大小可以从10mb到10 it。只有当文件大小超过800mb时才会出现问题。
InputStream inFileReader = channelSFtp.get(path); // file reading from ssh.
byte[] localbuffer = new byte[2048];
ByteArrayOutputStream bArrStream = new ByteArrayOutputStream();
int i = 0;
while (-1 != (i = inFileReader.read(buffer))) {
bArrStream.write(localbuffer, 0, i);
}
byte[] data = bArrStream.toByteArray();
inFileReader.close();
bos.close();
我们得到了错误
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2271)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140)
有什么可以帮上忙的吗?
发布于 2013-08-29 19:17:21
尝试使用
java.nio.MappedByteBuffer
..。
http://docs.oracle.com/javase/7/docs/api/java/nio/MappedByteBuffer.html
您可以将文件的内容映射到内存,而无需手动复制。高级操作系统提供了内存映射,Java提供了API来利用这一特性。
如果我的理解是正确的,那么内存映射不会将文件的全部内容加载到内存中(意思是“根据需要加载和卸载部分内容”),所以我猜一个10 up的文件不会占用您的内存。
发布于 2015-07-31 17:58:06
即使您可以增加JVM内存限制,但这也是不必要的,而且分配10 it这样的巨大内存来处理文件听起来有些夸张,而且会占用大量资源。
当前您使用的是一个"ByteArrayOutputStream“,它保留一个内部存储器来保存数据。代码中的这一行将最后读取的2KB文件块附加到此缓冲区的末尾:
bArrStream.write(localbuffer, 0, i);
bArrStream不断增长,最终会耗尽内存。
相反,你应该重新组织你的算法,并以流的方式处理文件:
InputStream inFileReader = channelSFtp.get(path); // file reading from ssh.
byte[] localbuffer = new byte[2048];
int i = 0;
while (-1 != (i = inFileReader.read(buffer))) {
//Deal with the current read 2KB file chunk here
}
inFileReader.close();
发布于 2013-08-29 18:46:55
Java虚拟机(JVM)使用固定的内存上限运行,您可以对其进行如下修改:
java -Xmx1024m ....
例如,上面的选项(-Xmx...)将限制设置为1024 to。您可以根据需要进行修改(在您的机器、操作系统等的限制范围内)请注意,这与传统应用程序不同,传统应用程序会根据需要从操作系统分配越来越多的内存。
但是,更好的解决方案是修改您的应用程序,这样您就不需要加载
整体
将文件一次性存入内存。这样就不需要调优JVM,也不会占用大量内存。
https://stackoverflow.com/questions/18508836
复制相似问题