Monday, February 18, 2013

Struts multipart upload Java heap space OutOfMemoryError

I have seen following java heap OOM error in struts 1.x library. The below stack trace does not contain the any of the application specific code, so it's little difficult to pin point or debug where exactly in the code the issue got originated. 

java.lang.OutOfMemoryError: Java heap space
    java.io.ByteArrayOutputStream.(ByteArrayOutputStream.java:60)
    org.apache.commons.fileupload.DeferredFileOutputStream.(DeferredFileOutputStream.java:131)
    org.apache.commons.fileupload.DefaultFileItem.getOutputStream(DefaultFileItem.java:558)
    org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:406)
 org.apache.struts.upload.CommonsMultipartRequestHandler.handleRequest(CommonsMultipartRequestHandler.java:193)
    org.apache.struts.util.RequestUtils.populate(RequestUtils.java:443)
    org.apache.struts.action.RequestProcessor.processPopulate(RequestProcessor.java:804)
    org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:203)
    org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
    org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 

Since I knew how to reproduce this error, I have fair understanding on which JSP page causing this error. So I took the heap dump (using -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath) and reproduced the error. And when I ran the heapdump bin file with JHAT server, I saw that there are many DeferredFileOutputStream objects created, which potentially causing the OOM error. I tried to locate this object in http://localhost:7000/class/0x31738c98 and I saw many instances...

 Class 0x31738c98
class org.apache.commons.fileupload.DeferredFileOutputStream
org.apache.commons.fileupload.DeferredFileOutputStream@0x140719b0 (37 bytes) : ??
org.apache.commons.fileupload.DeferredFileOutputStream@0x14ef8af8 (37 bytes) : ??
org.apache.commons.fileupload.DeferredFileOutputStream@0x240a4508 (37 bytes) : ??
org.apache.commons.fileupload.DeferredFileOutputStream@0x1e20a800 (37 bytes) : ??
org.apache.commons.fileupload.DeferredFileOutputStream@0x225969a8 (37 bytes) : ??
org.apache.commons.fileupload.DeferredFileOutputStream@0x161cb350 (37 bytes) : ??
org.apache.commons.fileupload.DeferredFileOutputStream@0x15cbf658 (37 bytes) : ??
org.apache.commons.fileupload.DeferredFileOutputStream@0x161cb5d0 (37 bytes) : ??
org.apache.commons.fileupload.DeferredFileOutputStream@0x161c9550 (37 bytes) : ??

Still I haven't gone into the source code of struts or apache library to figure out the actual root cause but I managed to identify the cause within the JSP file. 

Following line in the JSP file causing this issue.

html:form action='costCode' method='post' enctype='multipart/form-data'

Though there was no file upload functionality within this JSP, it's trying to send many options/checked selections data (100's of them) to action servlet. So by removing the enctype="multipart/form-data" attribute from the above tag the OOM got fixed!.


Monday, February 11, 2013

Real time shared drawing using Node.js and Socket.IO

Wednesday, February 6, 2013

Linked List Reverse circular way

Following code attempts to reverse a singly linked list in a circular fashion, for example, 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7  to 7 -> 1 -> 6 -> 2 -> 5 -> 3 -> 4


There are other ways to achieve this output in much efficient way but I just thought of posting this naive one O(n * n).

public void reverseSpecial(Node node) {
        Node temp = node;
        Node endbefore = null;
        Node head = temp;
        Node newstart = null;
        while (head != null && head.next != null) {
            while (temp != null && temp.next != null) {
                endbefore = temp;
                temp = temp.next;
            }
            if (newstart == null) { //first time
                newstart = temp;
            }
            temp.next = head;
            temp = head.next;
            head.next = endbefore;
            head = temp;
            endbefore.next = null;
        }