2010-07-05 2 views
14

Google App Engine 애플리케이션에 매우 간단한 업로드 양식을 사용하고 있습니다. 클라이언트 GWT 코드에서 내가 좋아하는 뭔가가 있습니다Blobstore에 업로드하면 Java 힙이 생성됩니다. OutOfMemoryError

final FormPanel uploadForm = new FormPanel(); 
uploadForm.setEncoding(FormPanel.ENCODING_MULTIPART); 
uploadForm.setMethod(FormPanel.METHOD_POST); 

uploadBtn.addClickHandler(new ClickHandler() { 
     @Override 
     public void onClick(ClickEvent event) { 
      blobstoreUploadURLService.getBlobstoreUploadURL("/banzai/process-pdf", new AsyncCallback<String>() { 

       @Override 
       public void onFailure(Throwable caught) { 
        // TODO Auto-generated method stub 
        System.err.println("FAILURE DURING UPLOAD SERVICE"); 
       } 

       @Override 
       public void onSuccess(String result) { 
        uploadForm.setAction(result); 
        uploadForm.submit(); 
       } 

      }); 
     } 
    }); 

을 그리고 파일을 선택합니다 new FileUpload()를 사용합니다. 흥미롭게도

WARNING: Error for /_ah/upload/agdrYnNrYWFychsLEhVfX0Jsb2JVcGxvYWRTZXNzaW9uX18YAww java.lang.OutOfMemoryError: Java heap space 
    at java.util.Arrays.copyOf(Arrays.java:2786) 
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:71) 
    at javax.mail.internet.MimeMultipart.readTillFirstBoundary(MimeMultipart.java:316) 
    at javax.mail.internet.MimeMultipart.parse(MimeMultipart.java:186) 
    at javax.mail.internet.MimeMultipart.getCount(MimeMultipart.java:109) 
    at com.google.appengine.api.blobstore.dev.UploadBlobServlet.handleUpload(UploadBlobServlet.java:135) 
    at com.google.appengine.api.blobstore.dev.UploadBlobServlet.access$000(UploadBlobServlet.java:72) 
    at com.google.appengine.api.blobstore.dev.UploadBlobServlet$1.run(UploadBlobServlet.java:100) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.google.appengine.api.blobstore.dev.UploadBlobServlet.doPost(UploadBlobServlet.java:98) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:713) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:806) 
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) 
    at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:51) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) 
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) 
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) 
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) 
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) 
    at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:70) 
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
    at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:349) 
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
    at org.mortbay.jetty.Server.handle(Server.java:326) 
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) 
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938) 

은, 여러 사람이 단지 this issue here보고 (전에이 문제에 실행 한 것, 그리고 당신 : 나는 로컬 또는 배포 된 인스턴스에서 그것을 테스트 할 때, 나는 로그에 다음과 같은 오류가 Google에서 좀 더 자세한 정보를 찾을 수 있습니다.)하지만 아무도 왜 그런 일이 발생하는지 전혀 알 수없는 것처럼 보이고 일부 사람들은 App Engine의 잘못이라고 제안하기도합니다. 그런 성급한 결론에 도달하기 전에 나는 먼저 여기에 물어볼 것이라고 생각했다. :)

그리고 흥미로운 점은 HTTP 라이브 헤더로 캡처 한 시도한 HTTP 헤더 (매우 작은 파일)이다.

 
    POST /_ah/upload/AMmfu6ZyyhSgz9uOR5VX4QBZeYADTB-aSejVvfGaogl3E_E8yPOLgtX9-0mob17IYfsaRZg-YP7aZrp1D4pDAwuKKm9CoNjeVx1eN2PwBro9x0PqXPeBLpQ/ALBNUaYAAAAATDFOaLPIvuEEhSS6F4HxMmf9xOb8lp0y/ HTTP/1.1 
    Host: kbskaar.appspot.com 
    User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
    Accept-Language: en-us,en;q=0.5 
    Accept-Encoding: gzip,deflate 
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 
    Keep-Alive: 115 
    Connection: keep-alive 
    Referer: http://kbskaar.appspot.com/ 

    Cookie: Lastname=Wong; Firstname=Ka%20Man%20Sophia; Username=kmswong%40uwaterloo.ca 
    Content-Type: multipart/form-data; boundary=---------------------------168072824752491622650073 
    Content-Length: 57 
     -----------------------------168072824752491622650073-- 



    HTTP/1.1 500 Internal Server Error 
    Server: Upload Server Built on Jul 1 2010 15:26:59 (1278023219) 
    Content-Type: text/html; charset=UTF-8 
    X-AppEngine-Estimated-CPM-US-Dollars: $0.375815 
    X-AppEngine-Resource-Usage: ms=7103 cpu_ms=16217 api_cpu_ms=0 
    Date: Mon, 05 Jul 2010 03:06:00 GMT 
    Pragma: no-cache 
    Expires: Fri, 01 Jan 1990 00:00:00 GMT 
    Cache-Control: no-cache, no-store, must-revalidate 
    Content-Length: 3211 
     ---------------------------------------------------------- 

아이디어가 있으면 알려 주시기 바랍니다. 감사!

+0

이 얼마나 큰 파일은 업로드되어이를 추가해야합니다? – markovuksanovic

+1

@markovuksanovic 모든 크기의 파일, 심지어 10KB 미만의 파일에서도 발생합니다. 분명히 너무 많이 업로드하고있는 것은 아닙니다. 물론 내가 생각한 첫 번째 것입니다. –

+0

또한 위의 코드 목록에서 파일의 전체 내용을 볼 수 있습니다. 이것은 57 바이트입니다. –

답변

15

좋아, 어색한 문제는 내가 양식의 FileInput 요소에 "이름"속성을 빠뜨린 것으로 밝혀졌습니다. 이로 인해 결과 스트림이 파싱 할 수 없게되어 MimeMultipart 파서의 메모리가 부족해질 수 있습니다.

문제는 내 것이었고 쉽게 해결할 수 있었지만, AppOngine의 버그는 단순한 실수로 인해 OutOfMemoryError 및 충돌이 발생하지 않으므로 여전히 고려해야합니다. 이것은 악의적 인 HTTP 요청을 만드는 것만으로도 DOS 취약점의 원인이 될 수 있습니다. Google에 버그 보고서를 보내 드리겠습니다.

+1

동일한 문제가 있었지만 createUploadUrl()에 전달 된 문자열에 선행 "/"가 없었습니다. 이로 인해 null 포인터 예외가 발생합니다 (http://code.google.com/p/googleappengine/issues/detail?id=2771 참조) –

+3

업로드하기 전에 FileUpload 구성 요소를 비활성화하면 (사용자가 값을 변경하지 못하도록 함) 메모리 부족 예외입니다. – pauli

4

및 양식에

enctype="multipart/form-data" 
+0

네,이게 나를 위해 해냈어 –

+0

나 한테도 그랬어. – csturtz

관련 문제