Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i work around the ClassCastException in java2d (Bug-ID 7172749)

I have the bad luck of suffering from a bug in java8, that doesn't seem to be a big issue for anybody else, so Oracle is not going to fix it before java9.
The bug has Bug-ID 7172749 (also note the related and duplicate bugs) and it just happens all the time on a certain linux machine.
I'm experiencing the problem on an Ubuntu 14.04.3 LTS with jdk1.8.0_u66.
However, on another box with Ubuntu 12.04.3 LTS and the same JDK version, i can't reproduce the problem at all.

What puzzles me is that this doesn't seem to be a showstopper for anybody else, so I guess maybe I'm making a particularly dump mistake.. I'm running the Oracle-JDK (as opposed to OpenJDK), because our customer uses the same version (albeit on windows) and the idea was to be close to their environment.

So, my question is, how to get around this problem (e.g. install X11-library xy, start my java-program with a magic -XXjava2dfailsafe parameter or sth along these lines)
and join the flock of people who can comfortably wait for the actual problem to be fixed by oracle?

Best regards Tobi

Btw, my stackstrace looks like this:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: sun.awt.image.BufImgSurfaceData cannot be cast to sun.java2d.xr.XRSurfaceData
    at sun.java2d.xr.XRPMBlitLoops.cacheToTmpSurface(XRPMBlitLoops.java:145)
    at sun.java2d.xr.XrSwToPMBlit.Blit(XRPMBlitLoops.java:353)
    at sun.java2d.SurfaceDataProxy.updateSurfaceData(SurfaceDataProxy.java:498)
    at sun.java2d.SurfaceDataProxy.replaceData(SurfaceDataProxy.java:455)
    at sun.java2d.SurfaceData.getSourceSurfaceData(SurfaceData.java:233)
    at sun.java2d.pipe.DrawImage.renderImageCopy(DrawImage.java:566)
    at sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:67)
    at sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:1014)
    at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3318)
    at sun.awt.image.ImageRepresentation.drawToBufImage(ImageRepresentation.java:813)
    at sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:1021)
[...]
like image 776
tobi42 Avatar asked Dec 09 '15 20:12

tobi42


1 Answers

I figured out a workaround for the problem.

In short: Start the JVM with the parameter -Dsun.java2d.xrender=false.

With that option, I didn't see the problem anymore.

Background Info

The Bug JDK-7172749 has now recently been fixed with jdk9 build 124 and the bugfix has been backported via JDK-8158068 to jdk8 update 112. You can download the jdk8u112 build preview from here: JDK8 Early Access Releases.

However, running this build didn't fix the problem for me.

My situation, where I experience the bug: I'm running jEdit and I see these ClassCastException after I resume my Linux from suspend-to-RAM. It's the same stacktrace:

10:04:10 [AWT-EventQueue-0] [error] AWT-EventQueue-0: java.lang.ClassCastException: sun.awt.image.BufImgSurfaceData cannot be cast to sun.java2d.xr.XRSurfaceData
10:04:10 [AWT-EventQueue-0] [error] AWT-EventQueue-0:  at sun.java2d.xr.XRPMBlitLoops.cacheToTmpSurface(XRPMBlitLoops.java:145)

The effect of this exception is, that the whole window of jEdit or parts are not drawn and stay white.

Looking at the patch for the backported bugfix, it actually fixed a ClassCastException in a different class, namely in sun.java2d.xr.XRRenderer.

So, it's not suprising that this didn't fix my problem.

Another google search revealed bug JDK-6975408 which made me aware of the system property sun.java2d.xrender.

More searching:

  • This option is described in System Properties for Java 2D Technology

    Quote:

    xrender

    Intended use: To enable the XRender-based Java 2D rendering pipeline for modern X11-based desktops, offering improved graphics performance.

    Introduced: Java SE 7

    Default value: false

    How to use: The pipeline is disabled by default, but may be enabled by setting the command line property -Dsun.java2d.xrender=true. Older X11 configurations may not be able to support XRender. The verbose form, -Dsun.java2d.xrender=True, can be used to enable a message to stdout indicating whether the pipeline was actually enabled.

  • Yes, it's a feature, that has been added with Java7: Xrender pipeline now in JDK7 master

    See also Enhancements in Java SE 7

  • And with Java8, it is now enabled by default: Java8: Xrender Java2D pipeline enabled by default

    According to the comments of this blog, the XRender pipeline is relevant only for Java2D, AWT and Swing - other GUI frameworks (JavaFX, SWT, ...) are not affected:

    Swing/AWT based application should benefit, SWT/JavaFX/lwjgl/jogl use other codepaths not related to Java2D.

    I didn't find something in the release notes, but in the source code, it's obvious, that the XRender pipeline is enabled by default: sun/awt/X11GraphicsEnvironment.java The commit that changed this, was done already in 2011, according to the ticket it was always on with the first jdk8 release. I guess, the reason, I didn't experience this bug earlier, is, that I probably used java7 as a runtime pretty long and eclipse is not affected.

Having a closer look again on the duplicated bug reports, there is already one, that would match the stacktrace:

It's bug JDK-8133723: sun.awt.image.BufImgSurfaceData cannot be cast to sun.java2d.xr.XRSurfaceData - it's really not a duplicate... However, reproducing this bug might be difficult. It appears only after a suspend-to-RAM cycle.

Update 1 - The trigger

The bug is triggered by changing the output display with xrandr, e.g.

xrandr --output eDP1 --auto --output DVI-1-0 --off

will immediately cause the ClassCastException. As I plug off my monitor before suspend, I assumed, it's the suspend-resume causing this, but that's wrong.

Update 2 - New Java Bug Ticket

There is a new java bug ticket now: JDK-8160328

Update 3 - Fixed with jdk-9-ea-b131

The bug ticket JDK-8160328 has been closed as duplicate of JDK-8147542 - and this one has been fixed with the latest EA build for java 9 (build 131 and later).

I could confirm, that I no longer get the ClassCastException when switching monitors with xrandr.

like image 59
adangel Avatar answered Oct 25 '22 06:10

adangel