[OpenJDK Rasterizer] Segfault in marlin code for Java 9 ea100

Jim Graham james.graham at oracle.com
Thu Feb 4 01:55:05 UTC 2016


Interesting, so this can happen with any custom Paint or Composite. 
Yes, re-entrance detection should be done.

Just out of curiosity - the 10% performance hit for the CLQ storage vs. 
thread-local - that was specifically only for the time it takes to 
retreive the Renderer, right?  I can't imagine why the entire rendering 
operation would take 10% longer for any mechanism that retrieves a 
cached Renderer - unless perhaps it was missing the cache and allocating 
a new one every time?  I would think a simple synchronized block around 
a small cache of Renderers would be nearly imperceptible compared to the 
amount of time spent inside the rendering process...

			...jim

On 2/3/2016 5:28 AM, Laurent Bourgès wrote:
> Phil,
>
> bug https://bugs.openjdk.java.net/browse/JDK-8148886
>
> Thanks for creating the bug !
>
> I spent some time tracking down the bug and make the diagnostic:
>
> 1. I enabled diagnostics:
>
> *-Dsun.java2d.renderer.log=true*
>
> *-Dsun.java2d.renderer.doChecks=true*
>
> **
>
> -Dsun.java2d.renderer.doStats=true
>
> -Dsun.java2d.renderer.logUnsafeMalloc=true
>
> I also enabled MarlinConst.doLogBounds in the Marlin code to have more
> details ... but it is not necessary.
>
> 2. The array checks detect invalid arrays (edgeBuckets / edgeBucketCounts)
>
> WARNING: Invalid array value at: *16438* = 24 from: 0 to: 312
> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> 0, ...]
>
> java.lang.Throwable
>              at
> org.marlin.pisces.IntArrayCache.check(IntArrayCache.java:139)
>              at org.marlin.pisces.IntArrayCache.fill(IntArrayCache.java:128)
>              at org.marlin.pisces.Renderer.dispose(Renderer.java:649)
>
>              at
> org.marlin.pisces.MarlinTileGenerator.dispose(MarlinTileGenerator.java:65)
> *            at sun.java2d.pipe.AAShapePipe.renderPath(AAShapePipe.java:150)
> *            at sun.java2d.pipe.AAShapePipe.fill(AAShapePipe.java:75)
>          at
> sun.java2d.pipe.PixelToParallelogramConverter.fill(PixelToParallelogramConverter.java:164)
>          at sun.java2d.pipe.ValidatePipe.fill(ValidatePipe.java:160)
> *        at sun.java2d.SunGraphics2D.fill(SunGraphics2D.java:2527)*
>
>          at org.faceless.pdf2.af
> <http://org.faceless.pdf2.af>$b.a(af$b.java:178)
>          at org.faceless.pdf2.af.a(af.java:843)
>          at org.faceless.pdf2.af.f(af.java:666)
>          at org.faceless.pdf2.am.a(am.java:726)
>          at org.faceless.pdf2.am.a(am.java:237)
>          at org.faceless.pdf2.b1.b(b1.java:441)
>          at org.faceless.pdf2.b1.a(b1.java:415)
>          at org.faceless.pdf2.b_.createContext(b_.java:101)
>
>          at
> sun.java2d.pipe.AlphaPaintPipe.startSequence(AlphaPaintPipe.java:84)
>          at sun.java2d.pipe.AAShapePipe.renderTiles(AAShapePipe.java:163)
> *        at sun.java2d.pipe.AAShapePipe.renderPath(AAShapePipe.java:149)
> *        at sun.java2d.pipe.AAShapePipe.fill(AAShapePipe.java:75)
>      at
> sun.java2d.pipe.PixelToParallelogramConverter.fill(PixelToParallelogramConverter.java:164)
>      at sun.java2d.pipe.ValidatePipe.fill(ValidatePipe.java:160)
> *    at sun.java2d.SunGraphics2D.fill(SunGraphics2D.java:2527)*
>
>      at org.faceless.pdf2.af
> <http://org.faceless.pdf2.af>$b.a(af$b.java:178)
>      at org.faceless.pdf2.af.a(af.java:843)
>      at org.faceless.pdf2.af.f(af.java:666)
>      at org.faceless.pdf2.am.a(am.java:726)
>      at org.faceless.pdf2.am.a(am.java:237)
>      at org.faceless.pdf2.am.a(am.java:941)
>      at org.faceless.pdf2.am.parsePage(am.java:154)
>      at org.faceless.pdf2.PagePainter.a(PagePainter.java:638)
>      at org.faceless.pdf2.PagePainter.a(PagePainter.java:362)
>      at org.faceless.pdf2.PagePainter.getSubImage(PagePainter.java:341)
>      at org.faceless.pdf2.PagePainter.getImage(PagePainter.java:310)
>      at PDFToImage.main(PDFToImage.java:155)
>
> Conclusion:
>
> There is a reentrance issue in Marlin when it uses thread local storage
> (default):
>
> *SunGraphics2D.fill()* -> AAShapePipe.renderTiles() ->
> AlphaPaintPipe.startSequence() ->
> org.faceless.pdf2.b_.createContext() -> *SunGraphics2D.fill() ...
> *
>
> 1. Reentrance is not supported when the RendererContext is stored in a
> thread-local variable (and reused among invocations).
>
> The segfault happens as the edgeBuckets / edgeBucketCounts arrays are
> empty (not zero-filled) and these arrays store "java pointers" (integer)
> to the Unsafe edge array !
>
> 2. I tested CLQ storage (concurrent linked queue) (~10% slower): it is
> not affected by this problem as the RendererContext is removed / added
> to the pool (not reused in recursion).
>
> Please use the simple workaround (CLQ):
>
> -Dsun.java2d.renderer.useThreadLocal=false
>
>
> I will then look at a proper solution: detect reentrance and use CLQ to
> store child RendererContexts ?
>
> Regards,
>
> Laurent
>
>
> Le 2 févr. 2016 21:26, "Phil Race" <philip.race at oracle.com
> <mailto:philip.race at oracle.com>> a écrit :
>
>     I have filed a bug https://bugs.openjdk.java.net/browse/JDK-8148886
>
>     I also downloaded the test case and see the crash.
>
>     FYI if you want to continue to test JDK9 builds and this is a blocker
>     for you (I suppose it is), then until it is fixed you can do
>
>     -Dsun.java2d.renderer=sun.dc.DuctusRenderingEngine
>     or
>     -Dsun.java2d.renderer=sun.java2d.pisces.PiscesRenderingEngine
>
>     -phil.
>


More information about the graphics-rasterizer-dev mailing list