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

1

13

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)
[...]
Mercymerdith answered 9/12, 2015 at 20:37 Comment(5)
I suspect, its also related to some awkward legacy coding style which we still have in certain areas of the software... Btw, the problem also appears with OpenJDK 1.8.0_45.Mercymerdith
The problem happened with icewm. Our Admin just installed xfce4, and when i run with xfce4 as the window manger, i can't reproduce the problem...I'll test a bit today and if it works, i'm going to add that as my answer..Mercymerdith
Follow-up: the Class-Cast exception is also gone on icewm now..i guess thatinstalling xfce4 caused some x11 libs to be updated ...or whatever.Mercymerdith
Problem is that now the same window where i got the CCEs before becomes aparently unresponsive, as if it is not repainted properly...so, my resume is: "how to get around this problem" => modernize that code, check e.g. whether we override some method (undeclared, maybe even by accident) or make very "creative" use of some features.Mercymerdith
oh, i tought i am the only one person in the whole world having this bizzare cast exceptions... this bug is ignored by me for 2 years, just did not know what to doBomar
T
15

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.

Toothwort answered 26/6, 2016 at 13:0 Comment(5)
Thanks a lot for sharingMercymerdith
I experienced that bug under Ubuntu. My Clients do use Windows. Will they may suffer from the bug too?Winter
@tokam I don't think so. The bug is very specific to the linux/solaris implementations (e.g. the usage of the xrender library)Toothwort
Thanks. It seems to work by me. I always got this error when a java app was running on the PC while TV set was turned on which is connected with the PC via HDMI. I use linux.Haldas
If you came here because of Netbeans Bug #219756, you can workaround it by including -J-Dsun.java2d.xrender=false in your $NETBEANS_HOME/etc/netbeans.conf as part of the netbeans_default_options.Allargando

© 2022 - 2024 — McMap. All rights reserved.