Modify

Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#15535 closed defect (fixed)

Freeze on Java 9 when you attempt to move node along a line using Extrusion tool

Reported by: andygol Owned by: team
Priority: critical Milestone: 17.11
Component: Core Version: tested
Keywords: extrusion freezing java9 javabug Cc: ris, bastiK, michael2402

Description (last modified by Don-vip)

I faced this bug in the latest (13097svn) and tested (13053) JOSM version on MacOS v10.13.1

$java --version
java 9.0.1
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

How to reproduce:

  1. Create a line or closed line (or use existing one)
  2. Make a try to move a node along the ways using Ctrl key (+ - combination on my Mac)(https://josm.openstreetmap.de/wiki/Help/Action/Extrude#MoveanodealongadjacentsegmentCtrl)
  3. JOSM is freezing and don't respond to any actions

Attachments (0)

Change History (34)

comment:1 by andygol, 7 years ago

Summary: JOSM is freezing when you attempt to move node using Extrusion toolJOSM is freezing when you attempt to move node along a line using Extrusion tool

comment:2 by andygol, 7 years ago

Description: modified (diff)

comment:3 by Don-vip, 7 years ago

Can't reproduce. Can you please check on another OS (Linux or Windows) to see if it's Mac-specific?

comment:4 by Don-vip, 7 years ago

Owner: changed from team to andygol
Status: newneedinfo

comment:5 by andygol, 7 years ago

It looks like JOSM with Java 9.0 doesn't work well on MacOS.

I've asked other guys to confirm this issue on MacOS with java8 update 141 and they could not reproduce it.

I will try to rollback on Java 8 and check if all is OK.

Last edited 7 years ago by andygol (previous) (diff)

comment:6 by andygol, 7 years ago

I've uninstalled Java JDK 9.0.1 that was installed via brew cask and rolled back to Java 8 update 151

All works as expected without visible issues.

It's good to close this ticket or mark it as the issue connected with java 9

Last edited 7 years ago by andygol (previous) (diff)

comment:7 by Don-vip, 7 years ago

Keywords: macosx java9 added
Summary: JOSM is freezing when you attempt to move node along a line using Extrusion toolFreeze on macOS / Java 9 when you attempt to move node along a line using Extrusion tool

comment:8 by Don-vip, 7 years ago

Owner: changed from andygol to team
Status: needinfonew

comment:9 by Don-vip, 7 years ago

Description: modified (diff)

comment:10 by Don-vip, 7 years ago

Do you launch JOSM via WebStart or command line? Please attach your status report.

comment:11 by andygol, 7 years ago

I run JOSM as a standalone application.

I tried to run JOSM via command line to get some information for reporting but except the message that Kendzi 3D was broken, I found nothing.

Also, +W hotkey for toggle wireframe mode didn't work as well.

comment:12 by Don-vip, 7 years ago

OK. It seems there is a large number of bugs specific to java 9 and macOS right now (108).

comment:13 by Don-vip, 7 years ago

One more question (there's a reason why we prefer status reports): what's your configured language, and what's your keyboard layout? macOS bugs are very often locale-specific.

comment:14 by andygol, 7 years ago

I have English (ABC-Extended) as primary and system language. I use JOSM with Default (auto determined) locale.

Along with it, I have installed Ukrainian and Russian keyboard layouts.

This is my current state report

URL:http://josm.openstreetmap.de/svn/trunk
Repository:UUID: 0c6e7542-c601-0410-84e7-c038aed88b3b
Last:Changed Date: 2017-10-29 19:52:48 +0100 (Sun, 29 Oct 2017)
Build-Date:2017-10-29 19:11:19
Revision:13053
Relative:URL: ^/trunk

Identification: JOSM/1.5 (13053 en) Mac OS X 10.13.1
OS Build number: Mac OS X 10.13.1 (17B48)
Memory Usage: 611 MB / 910 MB (65 MB allocated, but free)
Java version: 1.8.0_151-b12, Oracle Corporation, Java HotSpot(TM) 64-Bit Server VM
Screen: Display 69733568 1280x800
Maximum Screen Size: 1280x800
VM arguments: [-Djava.library.path=/Applications/JOSM.app/Contents/MacOS, -DLibraryDirectory=${HOME}/Library, -DDocumentsDirectory=${HOME}/Documents, -DApplicationSupportDirectory=${HOME}/Library/Application Support, -DCachesDirectory=${HOME}/Library/Caches, -DSandboxEnabled=false, -Dapple.laf.useScreenMenuBar=true, -Dcom.apple.macos.use-file-dialog-packages=true, -Dcom.apple.macos.useScreenMenuBar=true, -Dcom.apple.mrj.application.apple.menu.about.name=JOSM, -Dcom.apple.smallTabs=true]

comment:15 by Don-vip, 7 years ago

See similar bug #15567. Maybe not macOS specific.

comment:16 by Don-vip, 7 years ago

Priority: normalmajor

comment:17 by Don-vip, 7 years ago

Ticket #15567 has been marked as a duplicate of this ticket.

comment:18 by Don-vip, 7 years ago

Keywords: macosx removed
Milestone: 17.11
Summary: Freeze on macOS / Java 9 when you attempt to move node along a line using Extrusion toolFreeze on Java 9 when you attempt to move node along a line using Extrusion tool

Reproduced on Linux and Windows too.

comment:19 by Don-vip, 7 years ago

Keywords: javabug added
Priority: majorcritical

Waw, it seems to an infinite loop in Java2D rendering code!

comment:20 by bourges.laurent@…, 7 years ago

Could you make a thread dump (kill -3) to show the hot loop in marlin code. Dasher ?

Some details on the shape given to the renderer ?
Size, path, stroke attributes...

Laurent

comment:21 by Don-vip, 7 years ago

Sure, here are the first details. Here is our calling code:

    @Override
    public void paint(Graphics2D g2, MapView mv, Bounds box) {
        ...
        g2.setColor(helperColor);
        g2.setStroke(helperStrokeDash);
        // Draw a guideline along the normal.
        Line2D normline;
        Point2D centerpoint = mv.getPoint2D(p1.interpolate(p2, .5));
        normline = createSemiInfiniteLine(centerpoint, normalUnitVector, g2);
        g2.draw(normline); // <- infinite loop here (100% cpu)
        ...
    }

Variables state for the first call:

g2 sun.java2d.SunGraphics2D
	alphafill	MaskFill  (id=1370)	
	antialiasHint	2 [0x2] [^B]	
	backgroundColor	Color  (id=1374)	
	cachedFRC	FontRenderContext  (id=1375)	
	clipRegion	Region  (id=1377)	
	clipState	1 [0x1] [^A]	
	composite	AlphaComposite  (id=1379)	
	compositeState	0 [0x0] [^@ (NUL)]	
	constrainClip	null	
	constrainX	0 [0x0] [^@ (NUL)]	
	constrainY	0 [0x0] [^@ (NUL)]	
	devClip	Region  (id=1382)	
	drawpipe	PixelToParallelogramConverter  (id=1383)	
	eargb	-14336 [0xffffc800]	
	fillpipe	PixelToParallelogramConverter  (id=1383)	
	font	Font  (id=1389)	
	fontInfo	FontInfo  (id=1391)	
	fontMetrics	null	
	foregroundColor	Color  (id=1332)	
	fractionalMetricsHint	1 [0x1] [^A]	
	glyphVectorFontInfo	null	
	glyphVectorFRC	null	
	hints	null	
	imageComp	CompositeType  (id=1393)	
	imagepipe	DrawImage  (id=1395)	
	interpolationHint	-1 [0xffffffff]	
	interpolationType	1 [0x1] [^A]	
	lastCAblit	null	
	lastCAcomp	null	
	lcdTextContrast	140 [0x8c] [^Ì]	
	loops	RenderLoops  (id=1398)	
	paint	Color  (id=1332)	
	paintState	0 [0x0] [^@ (NUL)]	
	pixel	-14336 [0xffffc800]	
	renderHint	0 [0x0] [^@ (NUL)]	
	resolutionVariantHint	0 [0x0] [^@ (NUL)]	
	shapepipe	PixelToParallelogramConverter  (id=1383)	
	stroke	BasicStroke  (id=1336)	
	strokeHint	0 [0x0] [^@ (NUL)]	
	strokeState	2 [0x2] [^B]	
	surfaceData	BufImgSurfaceData  (id=1400)	
	textAntialiasHint	0 [0x0] [^@ (NUL)]	
	textpipe	AATextRenderer  (id=1406)	
	transform	AffineTransform  (id=1412)	
	transformState	0 [0x0] [^@ (NUL)]	
	transX	0 [0x0] [^@ (NUL)]	
	transY	0 [0x0] [^@ (NUL)]	
	usrClip	GeneralPath  (id=1414)	
	validFontInfo	false	
helperColor      java.awt.Color[r=255,g=200,b=0]
helperStrokeDash java.awt.BasicStroke
	cap	0
	dash	[4.0]
	dash_phase	0.0	
	join	0
	miterlimit	10.0	
	width	1.0	
centerPoint      Point2D.Double[546.7863882441737, 595.5292435631711]
normalUnitVector Point2D.Double[-0.7759523728971103, -0.6307914988293232]
normline         java.awt.geom.Line2D$Double
	x1	546.7863882441737
	x2	-3.3326895165083923E9
	y1	595.5292435631711
	y2	-2.709228261275939E9

And here is the infinite loop in sun.java2d.marlin.Dasher.lineTo (jdk 9.0.1):

    @Override
    public void lineTo(float x1, float y1) {
        ...
        float leftInThisDashSegment;
        float dashdx, dashdy, p;

        while (true) {
            leftInThisDashSegment = _dash[idx] - phase; // Stays to 4.0

            if (len <= leftInThisDashSegment) { // This is never true for us. Len is huge (4.29496704E9)
                _curCurvepts[0] = x1;
                _curCurvepts[1] = y1;
                goTo(_curCurvepts, 0, 4);

                // Advance phase within current dash segment
                phase += len;
                // TODO: compare float values using epsilon:
                if (len == leftInThisDashSegment) {
                    phase = 0f;
                    idx = (idx + 1) % dashLen;
                    dashOn = !dashOn;
                }
                return;
            }
            dashdx = _dash[idx] * cx; // cx = -0.7759524 => dashdx = -3.1038096
            dashdy = _dash[idx] * cy; // cy = -0.63079154 => dashdy = -2.5231662

            if (phase == 0f) { // true
                _curCurvepts[0] = x0 + dashdx; // x0 = -272518.53
                _curCurvepts[1] = y0 + dashdy; // y0 = -220992.17
            } else {
                p = leftInThisDashSegment / _dash[idx];
                _curCurvepts[0] = x0 + p * dashdx;
                _curCurvepts[1] = y0 + p * dashdy;
            }

            goTo(_curCurvepts, 0, 4); // _curCurvepts = [-272521.62, -220994.69, 3.0001056, 1.6513481, 2.9812324, 1.6598293, 2.7518036, 1.7459841, 4.590311, 1.6547815, 4.4771295, 1.6520241, 4.366947, 1.6513481, 4.2638865, 1.6513481]

            len -= leftInThisDashSegment; // 4.29496704E9 - 4.0 ==> we'll have to wait a very long time at this rate
            // Advance to next dash segment
            idx = (idx + 1) % dashLen; // (0 + 1) % 1 = 0
            dashOn = !dashOn;
            phase = 0f;
        }
        ...
    }

I'm trying with JDK 10-ea and latest release of Marvin now.

comment:22 by bourges.laurent@…, 7 years ago

Thanks so much for the report.

Marlin emits dashes in that loop for very long.
As jdk9 uses float, it suffers precision issue: the current accumulator is flawed.
I already experimented the kahan sum to preserve accuracy...
But I prefer using the double variant of Marlin which is the default in jdk10.

In Marlin 0.8.2 (@ github) I implemented a fast segment clipper,
as all these invisible dashes are counter productive.

I recommend anyway to fix your code in createSemiInfiniteLine() to:

  • crop the line to the clip window (+ extra margin): max length= sqrt (w2 + h2)
  • to have the best performance

It seems easy to do, isn't it ?

in reply to:  22 comment:23 by Don-vip, 7 years ago

Replying to bourges.laurent@…:

Thanks so much for the report.

You're welcome, thank you for your work on Marlin and coming discuss the problem with us :)

I recommend anyway to fix your code in createSemiInfiniteLine() to:

  • crop the line to the clip window (+ extra margin): max length= sqrt (w2 + h2)
  • to have the best performance

Looks like the best solution indeed. Do you need I create a bug report with reproducer code on Github, or is the previous information enough for you?

comment:24 by Don-vip, 7 years ago

By the way, same problem with jdk-10-ea+32.

comment:25 by Don-vip, 7 years ago

Cc: ris added

So basically we have to optimize the code added in #3832 / r2429 to fix this issue.

@ris: if you still remember what you did 8 years ago, would you like to have a look? :)

comment:26 by anonymous, 7 years ago

I read the code of createSemiInfLine() and it handles the viewport limits.
Maybe it is buggy (corner case ?)...

In your info, the Line2d is 500px to -2px so the scale is small.
How can the line length be 1E9 in Dasher ?

What is your scaling factor ?
I supposed the viewport corresponds to the painting area in pixel.

Certainly there is a confusion between device (pixel) & user (geo) spaces...

Ps: please send a reproducer on github or via marlin list or by mail

Laurent

comment:27 by Don-vip, 7 years ago

Cc: bastiK michael2402 added

Guys, this bug could interest you as well :)
@Laurent: sure I'll create a proper issue on Github, thanks for your help.

comment:28 by michael2402, 7 years ago

Just a short note without any testing

  • MapView does not use any scaling for painting. We use a 1:1 pixel mapping and do the math ourselves
  • I once tracked a bug where a line was drawn from (0,0) in East/North space. Since you were probably editing in europe, this might be where x0/y0 are.
  • Quick fix: You can use the MapViewPath class for drawing, it provides you with clipping.

comment:29 by Don-vip, 7 years ago

It is not really a Marlin bug. Rather a pure JDK bug:

System.out.println(g.getDeviceConfiguration().getBounds();

Java 8:
java.awt.Rectangle[x=0,y=0,width=1261,height=949]

Java 9:
java.awt.Rectangle[x=0,y=0,width=2147483647,height=2147483647] > WTF?!

That's why JOSM asks to the Java2D renderer to draw an infinite line. I have reproduced the freeze with Java 8 as well, with such an insane line length.

comment:30 by Don-vip, 7 years ago

The bug has been introduced on purpose (see javabug:8072682 / http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/aafc0a279f95).
This is so WTF I had to create https://github.com/CodeFX-org/java-9-wtf/pull/3

@Laurent: do you agree with what they did? It seems so wrong to me!

comment:31 by Don-vip, 7 years ago

Resolution: fixed
Status: newclosed

In 13135/josm:

fix #15535, see #11924 - make extrude mode work with Java9+

comment:32 by bourges.laurent@…, 7 years ago

I read the JBS bug and I agree the jdk change.
Graphics.getDeviceConfiguration() does not make sense on a buffered image.

However that jdk change hurts your code and the fix Graphics.getClipBounds() is the right thing to so.

You should inspect all your josm code to find any other usage of the buggy API.

Laurent

comment:33 by Don-vip, 7 years ago

OK thanks :) I already checked and did not find any other call to Graphics.getDeviceConfiguration() so it must be OK now :)

comment:34 by bourges.laurent@…, 7 years ago

FYI I added a comment to https://bugs.openjdk.java.net/browse/JDK-8072682

The API behaviour change in JDK9 should be mentioned in release notes (or migration guide)

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain team.
as The resolution will be set.
The resolution will be deleted. Next status will be 'reopened'.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.