2016-12-12 3 views
0

У меня проблема с кодом для загрузки файла с сервера. Это выглядит следующим образом:Glassfish 3.1.2.2 и OutOfMemoryError

response.reset(); 
    response.setContentType("audio/vnd.wave"); 
    File file = new File(filename); 
    FileInputStream stream = new FileInputStream(file); 
    long toWrite = file.length(); 
    filename = filename.substring(filename.lastIndexOf(File.separator) + 1, filename.length()); 
    response.setHeader("Content-disposition", "attachment; filename=\"" + filename + "\""); 
    //response.setHeader("Content-Length", String.valueOf(toWrite)); 
    response.setContentLength((int)toWrite); 
    response.getOutputStream().flush(); 
    response.flushBuffer(); 
    //Files.copy(file.toPath(), response.getOutputStream()); 
    byte data[] = new byte[1024*1024]; 
    int len; 
    while ((len = stream.read(data)) > 0) { 
     response.getOutputStream().write(data, 0, len); 
     response.getOutputStream().flush(); 
     response.flushBuffer(); 
     toWrite -= len; 
     System.out.println("left="+toWrite+" "+w.getBufferSize()+" "+w.getBytes().length); 
    } 
    stream.close(); 
    response.getOutputStream().flush(); 
    response.getOutputStream().close(); 
    context.responseComplete(); 

Для файлов более 1 Гб она заканчивается OOME (это один имеет около 1.4GB):

[#|2016-12-12T14:41:40.350+0100|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=99;_ThreadName=Thread-2;|left=389066752 8192 10737 
41824|#] 

[#|2016-12-12T14:41:41.237+0100|WARNING|glassfish3.1.2|javax.enterprise.resource.webcontainer.jsf.lifecycle|_ThreadID=99;_ThreadName=Thread-2;|#{showContractBean.downloadReco 
rding(item2.recFile)}: java.lang.OutOfMemoryError: Java heap space 
javax.faces.FacesException: #{showContractBean.downloadRecording(item2.recFile)}: java.lang.OutOfMemoryError: Java heap space 
     at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118) 
     at javax.faces.component.UICommand.broadcast(UICommand.java:315) 
     at javax.faces.component.UIData.broadcast(UIData.java:1093) 
     at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794) 
     at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259) 
     at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81) 
     at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
     at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) 
     at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) 
     at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217) 
     at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:357) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217) 
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279) 
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) 
     at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655) 
     at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595) 
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161) 
     at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331) 
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231) 
     at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317) 
     at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195) 
     at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860) 
     at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757) 
     at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056) 
     at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229) 
     at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) 
     at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) 
     at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) 
     at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) 
     at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) 
     at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) 
     at com.sun.grizzly.ContextTask.run(ContextTask.java:71) 
     at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) 
     at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) 
     at java.lang.Thread.run(Thread.java:745) 
Caused by: javax.faces.el.EvaluationException: java.lang.OutOfMemoryError: Java heap space 
     at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102) 
     at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) 
     ... 37 more 
Caused by: java.lang.OutOfMemoryError: Java heap space 
     at java.util.Arrays.copyOf(Arrays.java:2271) 
     at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118) 
     at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93) 
     at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153) 
     at org.apache.myfaces.webapp.filter.ExtensionsResponseWrapper$MyServletOutputStream.write(ExtensionsResponseWrapper.java:141) 
     at com.agreeya.telekonferencje.web.ShowContractBean.downloadRecording(ShowContractBean.java:1569) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
     at java.lang.reflect.Method.invoke(Method.java:606) 
     at javax.el.BeanELResolver.invokeMethod(BeanELResolver.java:779) 
     at javax.el.BeanELResolver.invoke(BeanELResolver.java:528) 
     at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:257) 
     at com.sun.el.parser.AstValue.invoke(AstValue.java:248) 
     at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:302) 
     at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) 
     at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88) 
     at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) 
     at javax.faces.component.UICommand.broadcast(UICommand.java:315) 
     at javax.faces.component.UIData.broadcast(UIData.java:1093) 
     at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794) 
     at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259) 
     at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81) 
     at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
     at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) 
     at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) 
     at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217) 
     at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:357) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217) 

Сервер имеет фиксированный 4 Гб памяти для домена, NewRatio устанавливается в 2 (значение по умолчанию).
Как вы можете видеть, что я пытался до сих пор:
1. Больше памяти для GlassFish
2. Меньший/больший массив буфера
3. Промывка ответ и выходной поток после каждой записи
4. Установить ContentLength в файл размер
5. Скопируйте потоки напрямую (FileStream -> OutputStream)
6. Установите Content-Length непосредственно как заголовок
не повезло. Выход должен быть потоковым, но это не так.

Есть ли что-то еще, что я должен попробовать?

На данный момент обновление GF до 4 невозможно, я боюсь.

|| EDIT

Наконец он работает, как ожидалось:

FacesContext context = FacesContext.getCurrentInstance(); 
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse(); 
ExtensionsResponseWrapper responseWrapper = (ExtensionsResponseWrapper)response; 
HttpServletResponse delegateResponse = responseWrapper.getDelegate(); 

try { 
    response.reset(); 
    response.setContentType("audio/vnd.wave"); 
    File file = new File(filename); 
    long toWrite = file.length(); 
    filename = filename.substring(filename.lastIndexOf(File.separator) + 1, filename.length()); 
    response.setHeader("Content-disposition", "attachment; filename=\"" + filename + "\""); 
    response.setHeader("Content-Length", String.valueOf(toWrite)); 
    response.setContentLength((int)toWrite); 
    ServletOutputStream out = delegateResponse.getOutputStream(); 
    out.flush(); 
    response.flushBuffer(); 
    Files.copy(file.toPath(), out); 
    response.getOutputStream().flush(); 
    response.getOutputStream().close(); 
    context.responseComplete(); 
} catch (IOException ex) { 
    log.log(Level.SEVERE, ex.getMessage(), ex); 
} 

ответ

0

Причина заключается в том, что класс ExtensionsResponseWrapper записывает вывод в ByteArrayOutputStream, увидеть код here.

Я не знаю, является ли это стандартным ответом MyFaces или используется из-за некоторой конфигурации в вашем приложении/GlassFish. Просмотрите код, который создает/принимает объект response.

+0

Кажется, что ByteArrayOutputStream.flush() не работает, и нет возможности сделать его потоковым. И мне не хватало [этот пост] (http://stackoverflow.com/questions/24505635/buffering-response-in-heap-space-cause-problems-for-large-files). Спасибо вам за помощь. – 13Homer

 Смежные вопросы

  • Нет связанных вопросов^_^