JDK-8202580 : Dashed BasicStroke randomly painted incorrectly, may freeze application
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 10.0.1,11
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux_ubuntu
  • CPU: x86_64
  • Submitted: 2018-05-02
  • Updated: 2021-06-28
  • Resolved: 2018-05-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 8
11 b14Fixed 8u311Fixed
Related Reports
Blocks :  
Description
ADDITIONAL SYSTEM INFORMATION :
OK: JDK 8
OK: JDK 9
BUG: OpenJDK 10.0.1 (Linux/Windows)
BUG: Oracle JDK 10.0.1
FIXED?: OpenJDK 11-ea+11

A DESCRIPTION OF THE PROBLEM :
It seems that "float[] dash" parameter of BasicStroke constructor is cached somewhere.
Maybe that cache ("recycleDashes" in Marlin (?) or something) is not thread safe (?)

REGRESSION : Last worked in version 8u162

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Dashed lines
ACTUAL -
Restarting application and invoking
Graphics2D.draw(dashed-basic-stroke) may result in one of 3 different *random* states:

State 1. Draws correctly and stable

State 2. Application freeze (looks like an infinite loop):
"AWT-EventQueue-0"
java.lang.Thread.State: RUNNABLE
     at sun.java2d.pipe.ShapeSpanIterator.lineTo(java.desktop@10.0.1/Native Method)
     at sun.java2d.marlin.DRendererContext$PathConsumer2DAdapter.lineTo(java.desktop@10.0.1/DRendererContext.java:235)
     at sun.java2d.marlin.DHelpers$PolyStack.popAll(java.desktop@10.0.1/DHelpers.java:650)
     at sun.java2d.marlin.DStroker.emitReverse(java.desktop@10.0.1/DStroker.java:615)
     at sun.java2d.marlin.DStroker.finish(java.desktop@10.0.1/DStroker.java:649)
     at sun.java2d.marlin.DStroker.moveTo(java.desktop@10.0.1/DStroker.java:505)
     at sun.java2d.marlin.DStroker.moveTo(java.desktop@10.0.1/DStroker.java:481)
     at sun.java2d.marlin.DDasher.goTo(java.desktop@10.0.1/DDasher.java:270)
     at sun.java2d.marlin.DDasher.lineTo(java.desktop@10.0.1/DDasher.java:372)
     at sun.java2d.marlin.DMarlinRenderingEngine.pathToLoop(java.desktop@10.0.1/DMarlinRenderingEngine.java:673)
     at sun.java2d.marlin.DMarlinRenderingEngine.pathTo(java.desktop@10.0.1/DMarlinRenderingEngine.java:633)
     at sun.java2d.marlin.DMarlinRenderingEngine.strokeTo(java.desktop@10.0.1/DMarlinRenderingEngine.java:451)
     at sun.java2d.marlin.DMarlinRenderingEngine.strokeTo(java.desktop@10.0.1/DMarlinRenderingEngine.java:224)
     at sun.java2d.marlin.DMarlinRenderingEngine.strokeTo(java.desktop@10.0.1/DMarlinRenderingEngine.java:197)
     at sun.java2d.pipe.LoopPipe.getStrokeSpans(java.desktop@10.0.1/LoopPipe.java:272)
     at sun.java2d.xr.XRRenderer.draw(java.desktop@10.0.1/XRRenderer.java:322)
     at sun.java2d.pipe.PixelToShapeConverter.drawRect(java.desktop@10.0.1/PixelToShapeConverter.java:57)
     at sun.java2d.pipe.ValidatePipe.drawRect(java.desktop@10.0.1/ValidatePipe.java:69)
     at sun.java2d.SunGraphics2D.drawRect(java.desktop@10.0.1/SunGraphics2D.java:2407)
(...)
     at javax.swing.plaf.ComponentUI.update(java.desktop@10.0.1/ComponentUI.java:161)
     at javax.swing.JComponent.paintComponent(java.desktop@10.0.1/JComponent.java:797)
     at javax.swing.JComponent.paint(java.desktop@10.0.1/JComponent.java:1074)
     at javax.swing.JComponent.paintChildren(java.desktop@10.0.1/JComponent.java:907)
     - locked <0x00000000f8062a70> (a java.awt.Component$AWTTreeLock)
     at javax.swing.JComponent.paint(java.desktop@10.0.1/JComponent.java:1083)
     at javax.swing.JComponent.paintToOffscreen(java.desktop@10.0.1/JComponent.java:5255)
     at javax.swing.BufferStrategyPaintManager.paint(java.desktop@10.0.1/BufferStrategyPaintManager.java:246)
     at javax.swing.RepaintManager.paint(java.desktop@10.0.1/RepaintManager.java:1313)
     at javax.swing.JComponent._paintImmediately(java.desktop@10.0.1/JComponent.java:5203)
     at javax.swing.JComponent.paintImmediately(java.desktop@10.0.1/JComponent.java:5013)
     at javax.swing.RepaintManager$4.run(java.desktop@10.0.1/RepaintManager.java:857)
     at javax.swing.RepaintManager$4.run(java.desktop@10.0.1/RepaintManager.java:840)
(...)

State 3. Draws sort of solid line instead of dashed one

---------- BEGIN SOURCE ----------
Sorry, due to nature of this bug I failed to reproduce this in a small test program.
Basically, the code is similar to this dashed BasicStroke tutorial:
https://docs.oracle.com/javase/tutorial/2d/geometry/strokeandfill.html
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
I can draw solid lines in my code, but 3rd party libraries and LAFs are out of control

FREQUENCY : often



Comments
Webrev: http://cr.openjdk.java.net/~lbourges/marlin/marlin-8202580.0/ See RFR thread: http://mail.openjdk.java.net/pipermail/2d-dev/2018-May/009183.html
04-05-2018

I managed reproducing the bug: it happens when dash phase is not 0 and the phase normalization is buggy in Dasher init() as it uses the complete dash array (large from cache) instead of the subpart [0 - dashLen[. I will write a test case reproducing both problems: solid lines (large dash sum) and hanging (dash sum < 0)
03-05-2018

Reported with JDK 10.0.1 and Ubuntu Linux or Windows. As per description, Dashed BasicStroke randomly paints incorrectly while freezing application. Checked this for reported JDK version in Windows 10 and couldn't confirm the issue convincngly, although the results seems varying randomly JDK 8u172, JDK 9, and JDK 10.0.1, though application didn't freeze in this case. The issue seems occurring randomly with solid line being drawn instead of dash. To verify, run the attached test case with respective JDK versions.
03-05-2018