Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8186021

Java2D's DuctusRenderingEngine has a MT bottleneck

XMLWordPrintable

    • 2d
    • x86
    • windows_7

      A DESCRIPTION OF THE REQUEST :
      JAI library has given this DuctusRenderingEngine, and almost all the methods of it static and synchronized, which is responsible for slow performace in multi-threaded environment.

      Always it's blocking the other threads to getRasterizer() and dropRasterizer() methods.

      its causes the Exception in thread "pool-1-thread-11" java.lang.OutOfMemoryError: Java heap space.


      JUSTIFICATION :
      "pool-1-thread-13" prio=6 tid=0x03da2c00 nid=0x4044 waiting for monitor entry [0x0457e000]
         java.lang.Thread.State: BLOCKED (on object monitor)
      at sun.dc.DuctusRenderingEngine.dropRasterizer(Unknown Source)
      - waiting to lock <0x26857f30> (a java.lang.Class for sun.dc.DuctusRenderingEngine)
      at sun.dc.pr.Rasterizer.dispose(Unknown Source)
      at sun.java2d.pipe.AAShapePipe.renderTiles(Unknown Source)
      at sun.java2d.pipe.AAShapePipe.renderPath(Unknown Source)
      at sun.java2d.pipe.AAShapePipe.fill(Unknown Source)
      at sun.java2d.pipe.PixelToParallelogramConverter.fill(Unknown Source)
      at sun.java2d.SunGraphics2D.fill(Unknown Source)


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      It must be non synchronized, so that performace can improve on production system.
      Rendering engine must be efficient to use all the resources as well.

      ---------- BEGIN SOURCE ----------


      import java.awt.Graphics2D;
      import java.awt.Image;
      import java.awt.image.BufferedImage;
      import java.io.File;
      import java.io.IOException;
      import java.io.RandomAccessFile;
      import java.util.List;
      import java.util.concurrent.Executors;
      import java.util.concurrent.ThreadPoolExecutor;

      import javax.imageio.IIOImage;
      import javax.imageio.ImageTypeSpecifier;
      import javax.imageio.metadata.IIOInvalidTreeException;

      import org.icepdf.core.exceptions.PDFException;
      import org.icepdf.core.exceptions.PDFSecurityException;
      import org.icepdf.core.pobjects.Document;
      import org.icepdf.core.pobjects.PDimension;
      import org.jpedal.examples.images.ConvertPagesToImages;

      import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet;
      import com.sun.media.imageio.plugins.tiff.TIFFDirectory;
      import com.sun.media.imageio.plugins.tiff.TIFFField;
      import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;
      import com.sun.media.imageio.plugins.tiff.TIFFTag;
      import com.sun.media.imageio.stream.FileChannelImageOutputStream;
      import com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadata;
      import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriter;
      import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi;

      public class TiffUtils {

      private static final int PDF_DPI = 72;

      public static final int CLR_RGB = BufferedImage.TYPE_INT_RGB;
      public static final int CLR_GRAY_SCALE = BufferedImage.TYPE_BYTE_GRAY;
      public static final int CLR_BLACK_WHITE = BufferedImage.TYPE_BYTE_BINARY;

      public static final int COMPRESSION_NONE = BaselineTIFFTagSet.COMPRESSION_NONE;
      public static final int COMPRESSION_CCITT_RLE = BaselineTIFFTagSet.COMPRESSION_CCITT_RLE;
      public static final int COMPRESSION_CCITT_T_4 = BaselineTIFFTagSet.COMPRESSION_CCITT_T_4;
      public static final int COMPRESSION_CCITT_T_6 = BaselineTIFFTagSet.COMPRESSION_CCITT_T_6;
      public static final int COMPRESSION_LZW = BaselineTIFFTagSet.COMPRESSION_LZW;
      public static final int COMPRESSION_JPEG = BaselineTIFFTagSet.COMPRESSION_JPEG;
      public static final int COMPRESSION_ZLIB = BaselineTIFFTagSet.COMPRESSION_ZLIB;
      public static final int COMPRESSION_PACKBITS = BaselineTIFFTagSet.COMPRESSION_PACKBITS;
      public static final int COMPRESSION_DEFLATE = BaselineTIFFTagSet.COMPRESSION_DEFLATE;

      protected static final int DEFAULT_DPI = 200;
      protected static final int DEFAULT_COLOR = CLR_RGB;
      protected static final int DEFAULT_COMPRESSION = COMPRESSION_LZW;
      protected static final float DEFAULT_COMPRESSION_QUALITY = 0.25f;




      public TiffUtils() {

      }

      public static void main(String[] args) {

      ThreadPoolExecutor threadPool=null;
      /*int corePoolSize = 5;
      int maximumPoolSize =10;
      int keepAliveTime =10;
      int queueSize = 50;*/
      // File filepath=new File("C:/PRAVIN/PDFtoTIf/1.pdf");
      /*Document d=new Document();
      try {
      d.setFile("C:/PRAVIN/PDFtoTIf/1.pdf");

      System.out.println("Writing pdf....");
      FileOutputStream stream=new FileOutputStream(new
      File("C:/PRAVIN/PDFtoTIf/1.tif"));
      d.saveToOutputStream(stream);
      stream.flush();
      stream.close();
      } catch (PDFException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (PDFSecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }*/


      /*try {
      d.setFile("C:/PRAVIN/PDFtoTIf/1.pdf");

      for(int i=47;i<50000;i++)
      {
      System.out.println("Writing pdf...."+i);
      FileOutputStream stream=new FileOutputStream(new
      File("C:/PRAVIN/PDFtoTIf/"+i+".pdf"));
      d.saveToOutputStream(stream);
      stream.flush();
      stream.close();

      }


      } catch (PDFException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
      } catch (PDFSecurityException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
      } catch (IOException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
      }

      */

      try {
      threadPool =(ThreadPoolExecutor)Executors.newFixedThreadPool(15);
      } catch (Exception e) {
      }

      System.out.println(System.currentTimeMillis()/(1000*60));
      for(int i=0;i<50000;i++)
      {
      //System.out.println(i);
      threadPool.execute(new CustomRun(i+1));
      }
      System.out.println(System.currentTimeMillis()/(1000*60));

      if(threadPool.getActiveCount()==0)
      threadPool.shutdown();

      }
      public boolean convertToTiff(String filePdfPath,String fileTifPath) {

      convertPDFtoTiff(filePdfPath,fileTifPath,"msisdn",18+"");
      System.out.println("converted done");

      return true;
      }

      public void convertPDFtoTiff(String pdfFilePath, String finalTiffFilePath, String tiffFileName, String circleId) {

      //BasicLogger.getLogger(circleId).writeToLog("convertPDFtoTiff start for " + tiffFileName + ",pdfFilePath=>" + pdfFilePath + ",finalTiffFilePath=>" + finalTiffFilePath);
      int dpi = 125;
      int color = CLR_GRAY_SCALE;
      int compression = COMPRESSION_LZW;
      float quality = 1f;
      try {
      convertToTiff(pdfFilePath, finalTiffFilePath, dpi, color, compression, quality);
      //BasicLogger.getLogger(circleId).writeToLog("Tiff Convertion process Completed.");
      } catch (Exception e) {
      //BasicLogger.getLogger(circleId).writeToLog("Exception in generating tiff=>" + e);
      finalTiffFilePath = null;
      }
      //BasicLogger.getLogger(circleId).writeToLog("convertPDFtoTiff end");
      }

      public void convertToTiff(String pdf, String tif, int dpi, int color, int compression, float quality) throws Exception {
      BufferedImage[] image = getImageFromPDF(pdf, dpi, color, compression);
      File file = new File(tif);

      if (file.exists()) {
      file.delete();
      }

      RandomAccessFile raf = new RandomAccessFile(file, "rw");
      FileChannelImageOutputStream fios = new FileChannelImageOutputStream(raf.getChannel());

      convert(image, fios, dpi, compression, quality);

      fios.flush();
      fios.close();
      raf.close();
      }

      protected void convert(BufferedImage[] image, Object os, int dpi, int compression, float quality) throws IOException {

      TIFFImageWriter writer = new TIFFImageWriter(new TIFFImageWriterSpi());
      TIFFImageWriteParam iwp = new TIFFImageWriteParam(writer.getLocale());

      writer.setOutput(os);
      writer.prepareWriteSequence(null);

      iwp.setCompressionMode(TIFFImageWriteParam.MODE_EXPLICIT);
      iwp.setCompressionType(getCompression(compression));

      if (!isCompressionLossless(compression)) {
      if (quality < 0.0F || quality > 1.0F)
      quality = DEFAULT_COMPRESSION_QUALITY;
      iwp.setCompressionQuality(quality);
      }

      for (int i = 0; i < image.length; i++) {
      ImageTypeSpecifier imageType = ImageTypeSpecifier.createFromRenderedImage(image[i]);
      TIFFImageMetadata imageMetadata = (TIFFImageMetadata) writer.getDefaultImageMetadata(imageType, iwp);
      imageMetadata = createImageMetadata(imageMetadata, image[i].getHeight(), image[i].getWidth(), dpi, compression, image[i].getType());
      writer.writeToSequence(new IIOImage(image[i], null, imageMetadata), iwp);
      }

      writer.endWriteSequence();
      writer.dispose();
      }

      protected TIFFImageMetadata createImageMetadata(TIFFImageMetadata imageMetadata, int height, int width, int dpi, int compression, int type) throws IIOInvalidTreeException {

      char[] cImageWidth = new char[]{(char) width};
      char[] cImageLength = new char[]{(char) height};
      char[] cResolutionUnit = new char[]{BaselineTIFFTagSet.RESOLUTION_UNIT_INCH};
      long[][] cDpiResolutionX = new long[][]{{(long) dpi, (long) 1}, {(long) 0, (long) 0}};
      long[][] cDpiResolutionY = new long[][]{{(long) dpi, (long) 1}, {(long) 0, (long) 0}};
      char[] cRowsPerStrip = new char[]{(char) (height)};
      char[] cStripOffsets = new char[]{(char) 1};
      char[] cStripByteCounts = new char[]{(char) 1};

      TIFFDirectory ifd = imageMetadata.getRootIFD();

      BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();

      TIFFTag tagImageLength = base.getTag(BaselineTIFFTagSet.TAG_IMAGE_LENGTH);
      TIFFTag tagImageWidth = base.getTag(BaselineTIFFTagSet.TAG_IMAGE_WIDTH);
      TIFFField fieldImageLength = new TIFFField(tagImageLength, TIFFTag.TIFF_SHORT, 1, cImageLength);
      TIFFField fieldImageWidth = new TIFFField(tagImageWidth, TIFFTag.TIFF_SHORT, 1, cImageWidth);
      ifd.addTIFFField(fieldImageLength);
      ifd.addTIFFField(fieldImageWidth);

      TIFFTag tagResUnit = base.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT);
      TIFFTag tagXRes = base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION);
      TIFFTag tagYRes = base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION);
      TIFFField fieldResUnit = new TIFFField(tagResUnit, TIFFTag.TIFF_SHORT, 1, cResolutionUnit);
      TIFFField fieldXRes = new TIFFField(tagXRes, TIFFTag.TIFF_RATIONAL, 1, cDpiResolutionX);
      TIFFField fieldYRes = new TIFFField(tagYRes, TIFFTag.TIFF_RATIONAL, 1, cDpiResolutionY);
      ifd.addTIFFField(fieldResUnit);
      ifd.addTIFFField(fieldXRes);
      ifd.addTIFFField(fieldYRes);

      TIFFTag tagRowsPerStrip = base.getTag(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP);
      TIFFTag tagStripOffSets = base.getTag(BaselineTIFFTagSet.TAG_STRIP_OFFSETS);
      TIFFTag tagStripByteCounts = base.getTag(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS);
      TIFFField fieldRowsPerStrip = new TIFFField(tagRowsPerStrip, TIFFTag.TIFF_SHORT, 1, cRowsPerStrip);
      TIFFField fieldStripOffsets = new TIFFField(tagStripOffSets, TIFFTag.TIFF_SHORT, 1, cStripOffsets);
      TIFFField fieldStripByteCounts = new TIFFField(tagStripByteCounts, TIFFTag.TIFF_SHORT, 1, cStripByteCounts);
      ifd.addTIFFField(fieldRowsPerStrip);
      ifd.addTIFFField(fieldStripOffsets);
      ifd.addTIFFField(fieldStripByteCounts);

      return imageMetadata;

      }

      protected boolean isCompressionLossless(int compression) {
      boolean lossless = true;
      for (int i = 0; i < TIFFImageWriter.compressionTypes.length; i++) {
      if (compression == TIFFImageWriter.compressionNumbers[i]) {
      lossless = TIFFImageWriter.isCompressionLossless[i];
      }
      }
      return lossless;
      }

      protected String getCompression(int compression) {
      String c = null;
      for (int i = 0; i < TIFFImageWriter.compressionTypes.length; i++) {
      if (compression == TIFFImageWriter.compressionNumbers[i]) {
      c = TIFFImageWriter.compressionTypes[i];
      }
      }
      return c;
      }

      private BufferedImage[] getImageFromPDF(String pdf, int dpi, int color, int compression) throws PDFException, PDFSecurityException, IOException {
      Document pdfFile = new Document();


      pdfFile.setFile(pdf);
      return getImageFromPDF(pdfFile, dpi, color, compression);
      }

      private BufferedImage[] getImageFromPDF(Document pdf, int dpi, int color, int compression) {
      float scale;
      float rotation = 0f;
      int width;
      int height;
      int numPgs = pdf.getNumberOfPages();

      List<Image>image1=null;

      BufferedImage[] image = new BufferedImage[numPgs];
      PDimension pd;
      Graphics2D g;

      for (int i = 0; i < numPgs; i++) {
      scale = (float) dpi / PDF_DPI;
      pd = pdf.getPageDimension(i, rotation, scale);
      width = (int) pd.getWidth();
      height = (int) pd.getHeight();
      image[i] = getBufferedImage(color, compression, width, height);

      //image[i].setAccelerationPriority(arg0);
      //creating graphics object of a single page
      /*image[i].setAccelerationPriority(0);
      g = image[i].createGraphics();*/

      // this line responsible to render the data on image


      // this using high memory to render and for 2 or 3 pdf OutOfMemoryException we observed.
      /*image[i]=(BufferedImage)pdf.getPageImage(
      i, GraphicsRenderingHints.PRINT, Page.BOUNDARY_CROPBOX, rotation, scale);*/

      /*System.out.println("Document Location--"+pdf.getDocumentLocation());
      System.out.println("Document Origni--"+pdf.getDocumentOrigin());*/
      try{
      ConvertPagesToImages converter = new ConvertPagesToImages(pdf.getDocumentLocation());
      if (converter.openPDFFile()) {
      int pageCount = converter.getPageCount();
      for (int page = 1; page <= pageCount; page++) {
      image[i] = converter.getPageAsImage(page, true);
      }
      }
      converter.closePDFfile();
      }catch (Exception e) {
      // TODO: handle exception
      e.printStackTrace();
      }
      //pdf.paintPage(i, g, GraphicsRenderingHints.PRINT, Page.BOUNDARY_CROPBOX, rotation, scale);


      //g.dispose();
      }


      pdf.dispose();

      return image;
      }

      protected BufferedImage getBufferedImage(int color, int compression, int width, int height) {
      BufferedImage image;
      if (compression == COMPRESSION_CCITT_RLE || compression == COMPRESSION_CCITT_T_4 || compression == COMPRESSION_CCITT_T_6 || color == CLR_BLACK_WHITE) {
      image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
      } else if (color == CLR_GRAY_SCALE) {
      image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
      } else {
      image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
      }
      return image;
      }

      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Please remove the static synchronized method or make it other object level.

            scfitch Stephen Fitch
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: