This discussion is archived
5 Replies Latest reply: Nov 14, 2012 6:32 AM by 603877 RSS

BufferedImage Java Heap Out of Memory

603877 Newbie
Currently Being Moderated
Hi All
I am building an application to generate QR and Bar Codes using the BufferedImage class. However I am getting "java.lang.OutOfMemoryError: GC overhead limit exceeded" error in tomcat though the heap space is set to 1024m.

I am now looking at the code and would like to know if there are any memory leaks. Below is the code snippet. Kindly advice me the best approach to deal with this code and BufferedImage to ensure that the object memory is freed up after use thus wont be facing the Out of memory issue.

-- This execute() method is called N times in loop___
public boolean execute(String prodCode, long barSeq) {
          try {
               String qrContent = prodCode + getQRSequence();
               String strSeq = String.format("%013d", barSeq);
          //     int checksum = getCheckSum(strSeq);
          //     String barContent = new StringBuilder(strSeq).append(checksum).toString();
               
               String barContent = strSeq;
               BufferedImage qrBI = QRImage(qrContent);
               BufferedImage barBI = BarImage(barContent);

               BufferedImage image = mergeQRBar(qrBI, barBI);
               imageList.offer(image);
               qrBarMap.put(barContent, qrContent);
               try {
                    Thread.sleep(20);
               } catch (Exception e) {
                    e.printStackTrace();
               }

               return true;

          } catch (Exception ex) {
               ex.printStackTrace();
               return false;
          }          
     }

private BufferedImage mergeQRBar(BufferedImage qrBI, BufferedImage barBI) {
          try {
               int w = Math.max(qrBI.getWidth(), barBI.getWidth());
               int h = qrBI.getHeight() + barBI.getHeight();

               BufferedImage combined = new BufferedImage(w, h,
                         BufferedImage.TYPE_INT_ARGB);

               Graphics2D g = combined.createGraphics();
               g.drawImage(qrBI, 0, 0, null);
               g.drawImage(barBI, 0, qrBI.getHeight(), null);

               return combined;
          } catch (Exception e) {
               e.printStackTrace();
               return null;
          }
     }

     private BufferedImage BarImage(String content) {
          try {
               // int width = 110;
               // int height = 30;

          //     EAN13Writer ean = new com.google.zxing.oned.EAN13Writer();
          //     BitMatrix bitMatrix = ean.encode(content, BarcodeFormat.EAN_13,barWidth, barHeight);
               
               
               BitMatrix bitMatrix = barean.encode(content, BarcodeFormat.CODE_128,barWidth, barHeight);
               
               BufferedImage im = MatrixToImageWriter.toBufferedImage(bitMatrix);
               BufferedImage bi = new BufferedImage(im.getWidth(),     im.getHeight() + 18, BufferedImage.TYPE_3BYTE_BGR);
               
               Graphics2D g = bi.createGraphics();
               g.setColor(Color.white);
               g.fillRect(0, 0, bi.getWidth(), bi.getHeight() + 18);
               g.drawImage(im, 0, 0, null);
               g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,     RenderingHints.VALUE_ANTIALIAS_ON);
               g.setColor(new Color(40, 30, 10));
               g.setFont(new Font("Dante", Font.PLAIN, 10));

               FontMetrics fm = g.getFontMetrics();
               int x = bi.getWidth() - fm.stringWidth(content) - 20;
               int y = (fm.getAscent() + (bi.getHeight() - (fm.getAscent() + fm
                         .getDescent()))) - 2;
               g.drawString(content, x, y);

               return bi;
          } catch (Exception e) {
               e.printStackTrace();
               return null;
          }
     }

     private BufferedImage QRImage(String content) {
          try {
               // int width = 110;
               // int height = 100;
               
               BitMatrix bitMatrix = qrean.encode(content, BarcodeFormat.QR_CODE, qrWidth, qrHeight);

               BufferedImage im = MatrixToImageWriter.toBufferedImage(bitMatrix);
               BufferedImage bi = new BufferedImage(im.getWidth(), im.getHeight(), BufferedImage.TYPE_INT_ARGB);
               
               Graphics2D g = bi.createGraphics();
               g.drawImage(im, 0, 0, null);
               g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,     RenderingHints.VALUE_ANTIALIAS_ON);
               g.setColor(new Color(40, 40, 40));
               g.setFont(new Font("Dante", Font.PLAIN, 12));

               FontMetrics fm = g.getFontMetrics();
               int x = bi.getWidth() - fm.stringWidth(content) - 20;
               int y = (fm.getAscent() + (bi.getHeight() - (fm.getAscent() + fm.getDescent()))) - 2; g.drawString(content, x, y);

               return bi;

          } catch (Exception e) {
               e.printStackTrace();
               return null;
          }
     }


Thanks & Regards
VM
  • 1. Re: BufferedImage Java Heap Out of Memory
    gimbal2 Guru
    Currently Being Moderated
    Use \
     tags when posting code to make it readable.
    
    If there is one thing I've learned, its that you don't spot memory leaks by staring at code. If you want to investigate memory usage you can use a profiler. Or in case of an environment which is JMX enabled (like a JavaEE environment), you could use JVisualVM to create a memory dump and analyze it.
    
    One thing I notice glancing over the code is that you don't dispose() Graphics objects you create when you're done with them. That is likely not the cause of the issue, but you still should do it.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
  • 2. Re: BufferedImage Java Heap Out of Memory
    TPD-Opitz-Consulting-com Expert
    Currently Being Moderated
    This is off topic to your request, but I'd like to point to this:
    return true;
    } catch (Exception ex) {
    ex.printStackTrace();
    return false;
    } 
    
    //...
    } catch (Exception e) {
    e.printStackTrace();
    return null;
    }
    Don't do this!
    At the first position you turn the exception into a return value. This hase 2 disadvantages:
    <ol><li>you loose exception details: the caller is not able to present the root cause to the user. the user must read the log to find the cause.</li>
    <li>the calling method must handle the error, eaven if it is not able to (but some other caller much higher in the call stack). This way you'll clutter your code with unnessesary code like: <tt>if(!execute("test",0)) return false;</tt></li></ol>

    At the second position you use null as the error indicator. This is eaven worse since a missed null check on this return value will cause a <tt>NullPointerException</tt> hiding the root cause...

    bye
    TPD
  • 3. Re: BufferedImage Java Heap Out of Memory
    603877 Newbie
    Currently Being Moderated
    @gimbal2 - I am quiet new to this and for posting the threads. Apologies for not following standards.
    I have taken the jprofile heap dump and trying to analyze it in Netbeans and found 90% memory size is taken by int[] object type.
    Any suggestion how can I know the memory leaks there.


    @TPD - Thanks - I will take note of that.

    Thanks
    VM
  • 4. Re: BufferedImage Java Heap Out of Memory
    EJP Guru
    Currently Being Moderated
    Why do you need to create both 'im' and 'bi' in both methods? If you could draw directly on 'im' you could cut your memory usage in half.
  • 5. Re: BufferedImage Java Heap Out of Memory
    603877 Newbie
    Currently Being Moderated
    Well again I am new to graphics programming.
    The idea was - "bi" is created to contain the image of "im" and a text content below "im" image. I didn't have idea how to extend "im" coordinates after it is created and returned.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points