2 u012161773 u012161773 于 2016.04.23 11:48 提问

javaweb上传文件到本机时,文件一直占用在内存中导致OutOfMemoryError,求前辈指点 5C

下面是上传代码和java内存监视图
以上传一个300M文件大小为示例

 @RequestMapping("/uploads")
    public @ResponseBody String upload(MultipartHttpServletRequest request,
            HttpServletResponse response) throws Exception {
        String result = "";
        // 获取上传的所有文件名
        Iterator<String> itr = request.getFileNames();
        MultipartFile mpf = null;
        while (itr.hasNext()) {
            // 取出文件
            mpf = request.getFile(itr.next());
            try {
                File file = new File(UPLOADFILEPATH);
                if (!file.exists()) {
                    file.mkdirs();
                }
                // 输出(保存)文件
                FileOutputStream fos = new FileOutputStream(new File(UPLOADFILEPATH + mpf.getOriginalFilename()));
                //获取文件的输入流并写入文件
                InputStream fis = mpf.getInputStream();
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = fis.read(buffer)) != -1) {
                    fos.write(buffer, 0, len);
                    fos.flush();
                }
                //关闭流
                fis.close();
                fos.close();
                mpf = null;
                result = "{\"success\":true}";
            } catch (IOException e) {
                result = "{\"success\":false}";
                e.printStackTrace();
            }

        }
        itr = null;
        System.gc();
        return result;
    }

下面是内存监视图
上传前的JvisualVM内存视图
上传前的JvisualVM内存视图
上传后的JvisualVM内存视图
上传后的JvisualVM内存视图
上传后的jconsole内存视图
上传后的jconsole内存视图
上传后的jconsole--old gen内存视图
上传后的jconsole--old gen内存视图
手动执行JvisualVM-GC清理后的内存视图
手动执行JvisualVM-GC清理后的内存视图

大概情况就是这样子了.文件上传本地后,内存一直被占用无法释放,导致内存溢出.困扰我很久了.希望有前辈能指点一下.谢谢!

3个回答

chenhchen1994
chenhchen1994   2016.04.23 12:04

是内存溢出吧 你把虚拟内存值设大一点

chenhchen1994
chenhchen1994 回复Soul柒月: http://blog.csdn.net/chenhchen1994/article/details/51226343 你可以去看看垃圾回收机制
一年多之前 回复
chenhchen1994
chenhchen1994 回复Soul柒月: 你要知道垃圾回收机制,并不是你不用了就直接执行了,只有当该对象不能再被程序中任何一个"活动的部分"所引用,此时才会调用来垃圾回收机制。当然也可以建议JVM执行垃圾回收机制,但不能百分百成功执行。你设置的-Xms512m -Xmx4096m 是在tomcat中设置的吗?
一年多之前 回复
u012161773
u012161773 回复On_the_orad: 我上传完成后使用的堆大小并没有降下来,继续上传使用的堆大小继续增加.然后就OutOfMemory了
一年多之前 回复
u012161773
u012161773 回复On_the_orad: -Xms512m -Xmx4096m这是我设置的.我启动程序后上传几个几百兆的文件后,就报错java.lang.OutOfMemoryError: Java heap space.这让我很不解.我本机物理内存是8G.
一年多之前 回复
chenhchen1994
chenhchen1994 回复Soul柒月: 你可以去看看 这个.http://blog.csdn.net/chenhchen1994/article/details/51219742
一年多之前 回复
chenhchen1994
chenhchen1994 回复Soul柒月: 有自动垃圾回收机制的。。。。。。 你上传JVM的虚拟内存不是指是的文件大小...
一年多之前 回复
u012161773
u012161773 如果占用内存不释放,内存设大一点也有溢出的一天.我只上传了一个300M不到的文件,堆大小暴增了1G左右.
一年多之前 回复
Renfr
Renfr   2016.04.23 15:31

文件读写完成后要及时关闭输入输出流,如果是未关闭输入输出流就会出现该文件正在被其他应用程序占用的现象。可是为什么一会

又可以打开文件了呢,是JAVA自动垃圾回收机制的问题,长时间不用该文件的输入输出流会默认回收掉。上传的文件时同名文件,所以是覆盖的。

在写文件过程中,LED程序已经将其更新状态为1,但是此时输入输出流未关闭,导致LED程序无法访问上传文件。呵呵,到此应该知道怎么解决了。

解决代码:

public void upload() throws Exception{
//以服务器的文件保存地址和源文件名建立上传文件输出流
xczl.setPath(getSavePath()+"\"+getUploadFileName());
FileOutputStream fos = new FileOutputStream(getSavePath()+"\"+getUploadFileName());
//以上传文件创建一个文件上传流
FileInputStream fis = new FileInputStream(upload);
//将上传文件的内容写入服务器
byte[] buffer = new byte[1024*1024];
int len = 0;
while((len = fis.read(buffer))>0)
{
fos.write(buffer,0,len);
}
fos.close();
fis.close();//关键代码
}

如果不行可以看下你的jvm内存设置的大小,建议设大点:
配置缓存步骤:点击 run 进入RunConfigurations 进入arguments 进入VM 在代码最下面添加如下代码:

-Xms512m -Xmx2048m -XX:MaxPermSize=1024m

Apply

u013321534
u013321534   2016.04.24 01:28

试试把fos.flush();去掉

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!