回忆一下:1年前在做断点续传因粗心编码导致的内存溢出问题。当时在做分片时,当分片容量大于512M时,内存溢出,抛出异常:java.lang.OutOfMemoryError: Java heap space。
分析一下:当时虚拟机堆内存正好设置为512M,当申请堆空间大于该值时出现如上异常。
今日重写代码测试,讲解出错的原因以及解决方案。
public static void testOutMemory() throws IOException {
//绝对路径
String inPath = "D:/TestFile/in/bigFileTest.zip";
String outPath = "D:/TestFile/out/bigFileTest.zip";
File inFile = new File(inPath);
File outFile = new File(outPath);
if (!inFile.exists()) {
//TODO 文件不存在
long fileLength = inFile.length();//文件大小,我的测试值为: 1820595407
ByteArrayOutputStream bos = new ByteArrayOutputStream((int) fileLength);//这一行会抛出异常
BufferedInputStream in = new BufferedInputStream(new FileInputStream(inFile));
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
int buf_size = 1024;
byte[] buffer = new byte[buf_size];
int len = 0;
while (-1 != (len = in.read(buffer, 0, buf_size))) {
bos.write(buffer, 0, len);
byte[] data = bos.toByteArray();
fileOutputStream.write(data);
fileOutputStream.flush();
fileOutputStream.close();
bos.close();
System.out.println("测试完成");
执行方法,在ByteArrayOutputStream bos = new ByteArrayOutputStream((int) fileLength);这一行会抛出异常,查看ByteArrayOutputStream构造方法,其中有一句为buf = new byte[size], 也正是在这一句抛出的异常,问题已经找到。
难道需要通过增加堆内存的方式来解决这个问题?当然不是。虽然可以暂时解决问题,但依然会埋下一枚地雷,当下一文件更大时,这个问题将会重新出现。
废话不多说,在代码中用一次缓存较大数据本身就不可取,上面的代码实现的文件传输本就不应该先把文件存放到内存,再将内存中的数据传输到其他位置,很明显这是一次很垃圾的编码。于是,优化如下:
public void testOutMemory() throws IOException {
// 绝对路径
String inPath = "D:/TestFile/in/bigFileTest.zip";
String outPath = "D:/TestFile/out/bigFileTest.zip";
File inFile = new File(inPath);
File outFile = new File(outPath);
if (!inFile.exists()) {
// TODO 文件不存在
BufferedInputStream in = new BufferedInputStream(new FileInputStream(inFile));
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
int buf_size = 1024;
byte[] buffer = new byte[buf_size];
int len = 0;
while (-1 != (len = in.read(buffer, 0, buf_size))) {
fileOutputStream.write(buffer, 0, len);//一次仅传输1K,不会溢出
fileOutputStream.flush();
fileOutputStream.close();
System.out.println("测试完成");
(PS:我的堆内存为2G,文件大小约1.7G,为什么会内存溢出了,在这篇文章中会进行详细探索)。
回复里面好像不参添加图片,为了说明这段代码不会出现OOM,刚才亲测文件下载,大约5个G,@我问佛陀 请见:
private void download(String downloadUrl, String path){
InputStream inputStream = null;
OutputStream outputStream = null;
try {
两周前就想把这点经验记录下来了,由于拖延症上身,直到刚才突然想起这件未完成的任务,今天是1024,在这个特别的日子里,祝所有程序猿兄弟姐妹们节日快乐!
上传功能一直很正常,直到上传了个500多兆的文件,报错提示:
“System.OutOfMemoryException”类型的异常在 mscorlib.dll 中发生,但未在用户代码中进行处理
对于内部用途和新的托管对象,确保要有足够的内存可...
今天一同事做了批量导入数据的功能,但是服务器老是死机。查看服务器内存8G的内存占了7G多,很明显是内存泄漏。后来发现对文件的操作的时候用到了ByteArrayInputStream,仔细查看代码看到了ByteArrayInputStream并没有释放,问题差不多就是这个了,然后想着关闭流,自然的想到了ByteArrayInputStream.close()方法。后经网络查证,close方法在Byt
ByteArrayOutputStream baos = makePdfByJson(result.toString(), “”);
if (baos.size() > 0) {
txtFilePath.setText(filePath.toString());
每次我上传带有部分数据的excel时,上传的文件都会损坏,并且我无法在aspose工作簿中使用此上传的文件(在某些情况下它也可以工作,我不知道为什么)。 甚至在我打开的同时,excel也会显示损坏的文件消息。 这是片段InputStream stream = file.getInputStream();OutputStream os = new FileOutputStream("path_t...
上一篇Android开发——常见的内存泄漏以及解决方案(一)中已经对部分可能会引发内存泄漏的情况进行了阐述,此篇将从图片、动画等资源角度介绍可能会造成内存泄漏的情况以及应对方法。6. 集合类导致内存泄漏很常见的一个例子就是图片的三级缓存结构,为了更好的用户体验,缓存机制必不可少,三级缓存分别为网络缓存,本地缓存以及内存缓存。...
1、java.lang.OutOfMemoryError: PermGen space
JVM管理两种类型的内存,堆和非堆。堆是给开发人员用的上面说的就是,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的。它和堆不同,运行期内GC不会释放空间。如果web app用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermSize设置较小,超出了也...
一、Maven编译过程中出现java.lang.OutOfMemoryError: Java heap space 错误,提示如下:
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2786)