2010-07-05 13 views
14

Sto facendo un semplice modulo di caricamento alla mia applicazione Google App Engine. Nel client di codice GWT ho qualcosa di simile:Il caricamento su Blobstore fornisce un heap 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(); 
       } 

      }); 
     } 
    }); 

e utilizza un new FileUpload() per selezionare il file. Quando ho provarlo, localmente o su un'istanza distribuito, ottengo il seguente errore nei registri:

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) 

È interessante notare che, molte persone sembrano aver incorrere in questo problema prima (basta guardare this issue here, e si possiamo trovarne qualcuna su Google) ma nessuno sembra avere alcuna idea del perché sta accadendo, e alcune persone suggeriscono addirittura che sia colpa di App Engine. Prima di saltare a conclusioni così sconcertanti, ho pensato di chiederlo prima :)

E nel caso sia interessante, ecco le intestazioni HTTP del tentativo di upload (un file molto piccolo), catturato con HTTP Live Headers.

 
    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 
     ---------------------------------------------------------- 

Per favore fatemi sapere se avete qualche idea. Grazie!

+0

Quanto è grande il file che si sta caricando? – markovuksanovic

+1

@markovuksanovic Succede per file di qualsiasi dimensione, anche file inferiori a 10 KB. Non è assolutamente il caso che sto semplicemente caricando troppo - è stata la prima cosa che ho pensato anch'io, ovviamente :) –

+0

Inoltre, puoi vedere l'intero contenuto del file nella lista di codici qui sopra. Questo è 57 byte. –

risposta

15

Ok, quindi il problema incredibilmente stupido si è rivelato essere che avevo omesso un attributo "nome" sull'elemento FileInput del modulo. Evidentemente ciò rende il flusso risultante incomparabile, il che fa sì che il parser di MimeMultipart abbia esaurito la memoria.

Anche se il problema ha finito per essere la mia, ed era facilmente risolvibile, che tuttora lo consideri questo un bug in AppEngine perché non c'è modo così un semplice errore dovrebbe causare un OutOfMemoryError e crash; questo potrebbe anche essere una fonte di vulnerabilità DOS semplicemente creando richieste HTTP maligne. Presenterò una segnalazione di bug con Google.

+1

Ho avuto lo stesso problema, ma non avevo nemmeno un "/" iniziale sulla stringa passata a createUploadUrl(). Ciò causa un'eccezione del puntatore nullo - vedi http://code.google.com/p/googleappengine/issues/detail?id=2771 –

+3

Se disattivi il componente FileUpload prima del caricamento (per impedire agli utenti di modificare il valore) ciò causa anche l'eccezione di memoria insufficiente. – pauli

4

e assicurarsi di aggiungere questo nella vostra forma

enctype="multipart/form-data" 
+0

sì, questo lo ha fatto per me –

+0

questo lo ha fatto anche per me – csturtz

Problemi correlati