Pivot
  1. Pivot
  2. PIVOT-815

Printing crashes with Out Of Memory exception

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0
    • Fix Version/s: 2.0.1
    • Component/s: wtk, wtk-terra
    • Environment:
      Windows 7 x64, Java 1.6.0_29

      Description

      Printing using Java's Printable interface... We have a single Pivot Window (it's an applet) and the layout isn't really complicated. Implementing print method of the Printable interface in our case boils down to drawing into the provided Graphics.

      This has worked perfectly until recently (not sure which version broke things, but we're talking last few weeks). Now when we print we get an "Out of Memory" exception. Call stack does not show any obvious anomalies like infinite loops and such, here it is:

      java.lang.OutOfMemoryError: Java heap space
      at java.awt.image.DataBufferInt.<init>(Unknown Source)
      at java.awt.image.Raster.createPackedRaster(Unknown Source)
      at java.awt.image.DirectColorModel.createCompatibleWritableRaster(Unknown Source)
      at java.awt.image.BufferedImage.<init>(Unknown Source)
      at sun.java2d.loops.GraphicsPrimitive.convertFrom(Unknown Source)
      at sun.java2d.loops.GraphicsPrimitive.convertFrom(Unknown Source)
      at sun.java2d.loops.MaskBlit$General.MaskBlit(Unknown Source)
      at sun.java2d.loops.Blit$GeneralMaskBlit.Blit(Unknown Source)
      at sun.java2d.pipe.DrawImage.blitSurfaceData(Unknown Source)
      at sun.java2d.pipe.DrawImage.renderImageCopy(Unknown Source)
      at sun.java2d.pipe.DrawImage.copyImage(Unknown Source)
      at sun.java2d.pipe.DrawImage.copyImage(Unknown Source)
      at sun.java2d.pipe.ValidatePipe.copyImage(Unknown Source)
      at sun.java2d.SunGraphics2D.drawImage(Unknown Source)
      at sun.java2d.SunGraphics2D.drawImage(Unknown Source)
      at sun.java2d.pipe.DrawImage.makeBufferedImage(Unknown Source)
      at sun.java2d.pipe.DrawImage.renderImageXform(Unknown Source)
      at sun.java2d.pipe.DrawImage.transformImage(Unknown Source)
      at sun.java2d.pipe.DrawImage.scaleImage(Unknown Source)
      at sun.java2d.pipe.DrawImage.copyImage(Unknown Source)
      at sun.java2d.pipe.DrawImage.copyImage(Unknown Source)
      at sun.java2d.pipe.ValidatePipe.copyImage(Unknown Source)
      at sun.java2d.SunGraphics2D.copyImage(Unknown Source)
      at sun.java2d.SunGraphics2D.drawImage(Unknown Source)
      at sun.java2d.SunGraphics2D.drawImage(Unknown Source)
      at sun.print.PeekGraphics.drawImage(Unknown Source)
      at org.apache.pivot.wtk.ApplicationContext$DisplayHost.paintVolatileBuffered(ApplicationContext.java:541)
      at org.apache.pivot.wtk.ApplicationContext$DisplayHost.paint(ApplicationContext.java:436)
      at com.barchart.realtime.core.service.PrintService.paint(PrintService.java:60)
      at com.barchart.realtime.core.service.PrintService.print(PrintService.java:84)
      at sun.print.RasterPrinterJob.printPage(Unknown Source)
      at sun.print.RasterPrinterJob.print(Unknown Source)

      If you need more info, do not hesitate to ask. I would have provided a test case, but it's not easy to extract code from a commercial product. Besides, I suspect this is some kind of obvious accidental mistake which should be easy to repeat with a very simple test case.pr

      1. PrintUtilities.java
        2 kB
        Drazen Dotlic
      2. pivot_511 - Applet.launch
        1 kB
        Sandro Martini
      3. ApplicationContext.java
        75 kB
        Sandro Martini
      4. ApplicationContext.java
        75 kB
        Sandro Martini

        Issue Links

          Activity

          Hide
          Sandro Martini added a comment -

          Finally this has been resolved.

          Drazen (and all others), be free to reopen the issue in case of problems.

          Show
          Sandro Martini added a comment - Finally this has been resolved. Drazen (and all others), be free to reopen the issue in case of problems.
          Hide
          Sandro Martini added a comment -

          latest version, with the improvement suggested by Drazen

          Show
          Sandro Martini added a comment - latest version, with the improvement suggested by Drazen
          Hide
          Drazen Dotlic added a comment -

          So, to summarize, the final (hopefully) fix should be to replace the "if" that tests if the Graphics instance is PrintGraphics to also test for PrinterGraphics (which is in java.awt.print package), like this:

          if (graphics instanceof PrintGraphics || graphics instanceof PrinterGraphics)

          { print(graphics); return; }

          Hope this helps.

          Show
          Drazen Dotlic added a comment - So, to summarize, the final (hopefully) fix should be to replace the "if" that tests if the Graphics instance is PrintGraphics to also test for PrinterGraphics (which is in java.awt.print package), like this: if (graphics instanceof PrintGraphics || graphics instanceof PrinterGraphics) { print(graphics); return; } Hope this helps.
          Hide
          Sandro Martini added a comment -

          Yes, I think that could be something changed in latest updates in Java ...

          At Office (where all works) I have Windows XP SP ... at 32 bit with the following JDK/JRE:
          java version "1.6.0_26"
          Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
          Java HotSpot(TM) Client VM (build 20.1-b02, mixed mode, sharing)
          I'm sorry but here I'm not able to test with different versions of Java ...

          I'll try asap at home on different PC (and different versions od OS and Java).

          Show
          Sandro Martini added a comment - Yes, I think that could be something changed in latest updates in Java ... At Office (where all works) I have Windows XP SP ... at 32 bit with the following JDK/JRE: java version "1.6.0_26" Java(TM) SE Runtime Environment (build 1.6.0_26-b03) Java HotSpot(TM) Client VM (build 20.1-b02, mixed mode, sharing) I'm sorry but here I'm not able to test with different versions of Java ... I'll try asap at home on different PC (and different versions od OS and Java).
          Hide
          Drazen Dotlic added a comment -

          Sandro and Noel,

          The patch does not work, but the reason is a bit strange.

          I just checked and for the other bug (Pivot-805, Labels won't print) we definitely concluded that the right interface to test would be if the Graphics instance implemented java.awt.PrintGraphics.

          However, on my machine (64-bit Windows 7, 32-bit Java 1.6.0_29) the interface is now java.awt.print.PrinterGraphics???

          I am not sure if this was a recent change in Java (probably) but that's the situation. I guess the test should include both of these interfaces (it might even be the case that the latter is more modern version of the former).

          This is a simple enough change, but I would definitely be interested to know which of these two interfaces you encounter on your machines while printing?

          Hoping for a quick patch, thanks again.

          Show
          Drazen Dotlic added a comment - Sandro and Noel, The patch does not work, but the reason is a bit strange. I just checked and for the other bug (Pivot-805, Labels won't print) we definitely concluded that the right interface to test would be if the Graphics instance implemented java.awt.PrintGraphics. However, on my machine (64-bit Windows 7, 32-bit Java 1.6.0_29) the interface is now java.awt.print.PrinterGraphics??? I am not sure if this was a recent change in Java (probably) but that's the situation. I guess the test should include both of these interfaces (it might even be the case that the latter is more modern version of the former). This is a simple enough change, but I would definitely be interested to know which of these two interfaces you encounter on your machines while printing? Hoping for a quick patch, thanks again.
          Hide
          Drazen Dotlic added a comment -

          OK, I just tried but our internal build doesn't seem to be synced with the trunk yet. Since it takes only a few minutes to try, I'll try again tonight and tomorrow. Will keep you posted.

          Show
          Drazen Dotlic added a comment - OK, I just tried but our internal build doesn't seem to be synced with the trunk yet. Since it takes only a few minutes to try, I'll try again tonight and tomorrow. Will keep you posted.
          Hide
          Drazen Dotlic added a comment -

          Sandro,

          I apologize for the lack of feedback. Our internal build "workflow" is much simplified if the patch ends up in the trunk, which we'll pick up and use more or less automatically. From what I've seen, the attempted fix has indeed landed in the trunk, so we should be able to test this easily.

          I am however tied up with some other work I must finish by the end of the week, so confirmation of the fix might require a few more days, but not more than that.

          Thanks again to all committers for their hard work.

          Show
          Drazen Dotlic added a comment - Sandro, I apologize for the lack of feedback. Our internal build "workflow" is much simplified if the patch ends up in the trunk, which we'll pick up and use more or less automatically. From what I've seen, the attempted fix has indeed landed in the trunk, so we should be able to test this easily. I am however tied up with some other work I must finish by the end of the week, so confirmation of the fix might require a few more days, but not more than that. Thanks again to all committers for their hard work.
          Hide
          Sandro Martini added a comment -

          sample eclipse launch file, to run a minimal test (using JDK AppletViewer) and try to Print from it

          Show
          Sandro Martini added a comment - sample eclipse launch file, to run a minimal test (using JDK AppletViewer) and try to Print from it
          Hide
          Sandro Martini added a comment -

          latest version of patched source (from trunk), to simplify test

          Show
          Sandro Martini added a comment - latest version of patched source (from trunk), to simplify test
          Hide
          Sandro Martini added a comment -

          Hi all,
          after some tests from latest fix (from Noel), now all seem to work in my environment.
          Note that with this fix even PIVOT-511 should be solved !!

          @Drazen:
          the fix from Noel disable double buffering, but without using Swing classes, it's based only on Pivot and AWT Classes.
          In attach I'll put (in a few minutes) an updated version of updated class (ApplicationContext.java), so you can easily try and tell to us if this if Ok even for you now.

          @All: this is an important fix for Pivot, please can you test and give some feedback ?

          Thank you very much.

          Show
          Sandro Martini added a comment - Hi all, after some tests from latest fix (from Noel), now all seem to work in my environment. Note that with this fix even PIVOT-511 should be solved !! @Drazen: the fix from Noel disable double buffering, but without using Swing classes, it's based only on Pivot and AWT Classes. In attach I'll put (in a few minutes) an updated version of updated class (ApplicationContext.java), so you can easily try and tell to us if this if Ok even for you now. @All: this is an important fix for Pivot, please can you test and give some feedback ? Thank you very much.
          Hide
          Drazen Dotlic added a comment -

          Sandro,

          please take a look at the attached Java source - double buffering is indeed disabled during print.

          Show
          Drazen Dotlic added a comment - Sandro, please take a look at the attached Java source - double buffering is indeed disabled during print.
          Hide
          Sandro Martini added a comment -

          To fix thing is a good way we need a better test case ... at least a minimal sample from Drazen sources.
          In any case I'll try from appletviewer ...

          But note that as written in the article linked here ( https://issues.apache.org/jira/browse/PIVOT-805?focusedCommentId=13143346&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13143346 ) huge memory usage during print could be due to double beffering / wrong scaling of graphics from Java (Java2D) ... a workaround could be to disable it during print (from Browser and/or using only java functions), BUT so we need a clear way to understand when the browser is Printing ... if someone has some idea ...

          Show
          Sandro Martini added a comment - To fix thing is a good way we need a better test case ... at least a minimal sample from Drazen sources. In any case I'll try from appletviewer ... But note that as written in the article linked here ( https://issues.apache.org/jira/browse/PIVOT-805?focusedCommentId=13143346&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13143346 ) huge memory usage during print could be due to double beffering / wrong scaling of graphics from Java (Java2D) ... a workaround could be to disable it during print (from Browser and/or using only java functions), BUT so we need a clear way to understand when the browser is Printing ... if someone has some idea ...
          Hide
          Sandro Martini added a comment -

          Probably the fix for pivot-805 should be changed a little ... because now when have this issue.

          Another test could be to try to add more memory to applets (if possible), just to see what happens.

          Show
          Sandro Martini added a comment - Probably the fix for pivot-805 should be changed a little ... because now when have this issue. Another test could be to try to add more memory to applets (if possible), just to see what happens.
          Hide
          Drazen Dotlic added a comment -

          OK, great, I will direct my colleague's attention to this patch, he is the one maintaining the build. Being in the US, he'll probably see this in 6 hours of so, hopefully quickly integrate, then I'll test and we'll get back to you with our findings.

          Thanks again.

          Show
          Drazen Dotlic added a comment - OK, great, I will direct my colleague's attention to this patch, he is the one maintaining the build. Being in the US, he'll probably see this in 6 hours of so, hopefully quickly integrate, then I'll test and we'll get back to you with our findings. Thanks again.
          Hide
          Noel Grandin added a comment -

          Please try this patch:

          Index: ApplicationContext.java
          ===================================================================
          — ApplicationContext.java (revision 1196545)
          +++ ApplicationContext.java (working copy)
          @@ -21,6 +21,7 @@
          import java.awt.Graphics;
          import java.awt.Graphics2D;
          import java.awt.GraphicsConfiguration;
          +import java.awt.PrintGraphics;
          import java.awt.RenderingHints;
          import java.awt.Transparency;
          import java.awt.dnd.DnDConstants;
          @@ -425,6 +426,10 @@

          @Override
          public void paint(Graphics graphics) {
          + if (graphics instanceof PrintGraphics)

          { + print(graphics); + return; + }

          // Intersect the clip region with the bounds of this component
          // (for some reason, AWT does not do this automatically)
          graphics.clipRect(0, 0, getWidth(), getHeight());
          @@ -455,6 +460,25 @@
          }

          @Override
          + public void print(Graphics graphics) {
          + // Intersect the clip region with the bounds of this component
          + // (for some reason, AWT does not do this automatically)
          + graphics.clipRect(0, 0, getWidth(), getHeight());
          +
          + java.awt.Rectangle clipBounds = graphics.getClipBounds();
          + if (clipBounds != null
          + && !clipBounds.isEmpty()) {
          + try

          { + // When printing, there is no point in using offscreen buffers. + paintDisplay((Graphics2D)graphics); + }

          catch (RuntimeException exception)

          { + System.err.println("Exception thrown during print(): " + exception); + throw exception; + }

          + }
          + }
          +
          + @Override
          public void update(Graphics graphics)

          { paint(graphics); }
          Show
          Noel Grandin added a comment - Please try this patch: Index: ApplicationContext.java =================================================================== — ApplicationContext.java (revision 1196545) +++ ApplicationContext.java (working copy) @@ -21,6 +21,7 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; +import java.awt.PrintGraphics; import java.awt.RenderingHints; import java.awt.Transparency; import java.awt.dnd.DnDConstants; @@ -425,6 +426,10 @@ @Override public void paint(Graphics graphics) { + if (graphics instanceof PrintGraphics) { + print(graphics); + return; + } // Intersect the clip region with the bounds of this component // (for some reason, AWT does not do this automatically) graphics.clipRect(0, 0, getWidth(), getHeight()); @@ -455,6 +460,25 @@ } @Override + public void print(Graphics graphics) { + // Intersect the clip region with the bounds of this component + // (for some reason, AWT does not do this automatically) + graphics.clipRect(0, 0, getWidth(), getHeight()); + + java.awt.Rectangle clipBounds = graphics.getClipBounds(); + if (clipBounds != null + && !clipBounds.isEmpty()) { + try { + // When printing, there is no point in using offscreen buffers. + paintDisplay((Graphics2D)graphics); + } catch (RuntimeException exception) { + System.err.println("Exception thrown during print(): " + exception); + throw exception; + } + } + } + + @Override public void update(Graphics graphics) { paint(graphics); }
          Hide
          Drazen Dotlic added a comment -

          Hi Noel,

          thanks for the very quick response.

          Unfortunately, we can't call a different method - our PrintService is actually based on this code: http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/Printing/PrintUtilities.java (we renamed PrintUtilities to PrintService, we added a bit of code to better support scaling content to the page but nothing of significance has been modified; I've also attached the original file to this issue).

          Ultimately, what we're printing is an AWT Component, so there's no Pivot (conceptually) at this level (PrintService class is in a JAR "low" in our dependency graph and does not depend on Pivot in any way).

          There is a way for you to detect this situation - Graphics instance will be of a different type when you print - it will be PrintGraphics. This has been confirmed by an unrelated patch for the issue 805: https://issues.apache.org/jira/browse/PIVOT-805

          Hope this helps, if not, just let me know. We're very grateful for your support and all the effort in building Pivot. Keep up the good work!

          Show
          Drazen Dotlic added a comment - Hi Noel, thanks for the very quick response. Unfortunately, we can't call a different method - our PrintService is actually based on this code: http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/Printing/PrintUtilities.java (we renamed PrintUtilities to PrintService, we added a bit of code to better support scaling content to the page but nothing of significance has been modified; I've also attached the original file to this issue). Ultimately, what we're printing is an AWT Component, so there's no Pivot (conceptually) at this level (PrintService class is in a JAR "low" in our dependency graph and does not depend on Pivot in any way). There is a way for you to detect this situation - Graphics instance will be of a different type when you print - it will be PrintGraphics. This has been confirmed by an unrelated patch for the issue 805: https://issues.apache.org/jira/browse/PIVOT-805 Hope this helps, if not, just let me know. We're very grateful for your support and all the effort in building Pivot. Keep up the good work!
          Hide
          Noel Grandin added a comment -

          Can you try this patch, and change your PrintService code to call print(Graphics) instead of paint(Graphics)

          Index: ApplicationContext.java
          ===================================================================
          — ApplicationContext.java (revision 1196545)
          +++ ApplicationContext.java (working copy)
          @@ -455,6 +455,33 @@
          }

          @Override
          + public void print(Graphics graphics) {
          + // Intersect the clip region with the bounds of this component
          + // (for some reason, AWT does not do this automatically)
          + graphics.clipRect(0, 0, getWidth(), getHeight());
          +
          + java.awt.Rectangle clipBounds = graphics.getClipBounds();
          + if (clipBounds != null
          + && !clipBounds.isEmpty()) {
          + try {
          + // When printing, there is no point in using offscreen buffers.
          + paintDisplay((Graphics2D)graphics);
          +
          + if (debugPaint)

          { + graphics.setColor(new java.awt.Color(random.nextInt(256), + random.nextInt(256), random.nextInt(256), 75)); + graphics.fillRect(0, 0, getWidth(), getHeight()); + }

          + } catch (RuntimeException exception)

          { + System.err.println("Exception thrown during print(): " + exception); + throw exception; + }

          + }
          +
          + paintPending = false;
          + }
          +
          + @Override
          public void update(Graphics graphics)

          { paint(graphics); }
          Show
          Noel Grandin added a comment - Can you try this patch, and change your PrintService code to call print(Graphics) instead of paint(Graphics) Index: ApplicationContext.java =================================================================== — ApplicationContext.java (revision 1196545) +++ ApplicationContext.java (working copy) @@ -455,6 +455,33 @@ } @Override + public void print(Graphics graphics) { + // Intersect the clip region with the bounds of this component + // (for some reason, AWT does not do this automatically) + graphics.clipRect(0, 0, getWidth(), getHeight()); + + java.awt.Rectangle clipBounds = graphics.getClipBounds(); + if (clipBounds != null + && !clipBounds.isEmpty()) { + try { + // When printing, there is no point in using offscreen buffers. + paintDisplay((Graphics2D)graphics); + + if (debugPaint) { + graphics.setColor(new java.awt.Color(random.nextInt(256), + random.nextInt(256), random.nextInt(256), 75)); + graphics.fillRect(0, 0, getWidth(), getHeight()); + } + } catch (RuntimeException exception) { + System.err.println("Exception thrown during print(): " + exception); + throw exception; + } + } + + paintPending = false; + } + + @Override public void update(Graphics graphics) { paint(graphics); }

            People

            • Assignee:
              Sandro Martini
              Reporter:
              Drazen Dotlic
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development