Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uploading to Blobstore gives a Java heap OutOfMemoryError

I'm doing a very simple upload form to my Google App Engine application. In the client GWT code I have something like:

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();
                }

            });
        }
    });

And it uses a new FileUpload() to select the file. When I test it, either locally or on a deployed instance, I get the following error in the logs:

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)

Interestingly enough, several people seem to have run into this issue before (just look at this issue here, and you can find a few more on Google) but nobody seems to have any idea why it's happening, and some people are even suggesting it's App Engine's fault. Before I jumped to such rash conclusions, I thought I'd ask here first :)

And in case it's interesting, here's the HTTP headers of the attempted upload (a very small file), captured with 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
        ----------------------------------------------------------

Please let me know if you have any ideas. Thanks!

like image 379
Adrian Petrescu Avatar asked Jul 05 '10 03:07

Adrian Petrescu


People also ask

What causes Java Lang OutOfMemoryError Java heap space?

lang. OutOfMemoryError exception. Usually, this error is thrown when there is insufficient space to allocate an object in the Java heap. In this case, The garbage collector cannot make space available to accommodate a new object, and the heap cannot be expanded further.

How do you fix heap memory problems?

There are several ways to eliminate a heap memory issue: Increase the maximum amount of heap available to the VM using the -Xmx VM argument. Use partitioning to distribute the data over additional machines. Overflow or expire the region data to reduce the heap memory footprint of the regions.


1 Answers

Okay, so the incredibly silly problem turned out to be that I had left out a "name" attribute on the FileInput element of the form. This evidently makes the resulting stream unparseable, which causes the MimeMultipart parser to run out of memory.

Even though the problem ended up being mine, and was easily fixable, I still consider this a bug in AppEngine because there's no way such a simple mistake should cause an OutOfMemoryError and crash; this could also be a source of DOS vulnerabilities just by crafting malicious HTTP requests. I'll file a bug report with Google.

like image 169
Adrian Petrescu Avatar answered Oct 23 '22 11:10

Adrian Petrescu