我如何解决 java2d 中的 ClassCastException(错误 ID 7172749)

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

我运气不好 java8, 这对其他人来说似乎不是什么大问题,因此 Oracle 不会在 java9.
之前修复它 该错误有 Bug-ID 7172749(另请注意相关和重复的错误) 它只是 一直 在某台 linux 机器上发生。
我在使用 jdk1.8.0_u66.
的 Ubuntu 14.04.3 LTS 上遇到问题 但是,在另一个装有 Ubuntu 12.04.3 LTS 和 same JDK 版本的盒子上,我根本无法重现该问题。

令我困惑的是,这似乎对其他任何人来说都不是一个障碍,所以我想也许我犯了一个特别愚蠢的错误…… 我是 运行 Oracle-JDK(与 OpenJDK 相反),因为我们的客户使用相同的版本(尽管在 windows 上)并且我的想法是接近他们的环境。

所以,我的问题是,如何解决这个问题(例如,安装 X11-library xy,使用魔法 -XXjava2dfailsafe 参数启动我的 java-程序,或者沿着这些行)
并加入可以舒适地等待 oracle 解决实际问题的人群?

此致 托比

顺便说一句,我的 stackstrace 看起来像这样:

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)
[...]

我找到了解决该问题的解决方法

简而言之:使用参数-Dsun.java2d.xrender=false启动JVM。

有了那个选项,我就再也看不到问题了。

背景信息

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.

但是,运行这个版本没有解决我的问题。

我遇到错误的情况:我是 运行 jEdit,在我从挂起到 RAM 恢复 Linux 后看到这些 ClassCastException。 这是相同的堆栈跟踪:

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)

此异常的影响是,整个 window jEdit 或部分未绘制并保持白色。

查看 patch for the backported bugfix,它实际上修复了另一个 class 中的 ClassCastException,即 sun.java2d.xr.XRRenderer.

因此,这并没有解决我的问题也就不足为奇了。

另一个 google 搜索显示 bug JDK-6975408 这让我知道系统 属性 sun.java2d.xrender.

更多搜索:

  • 此选项在 System Properties for Java 2D Technology

    中有描述

    引用:

    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.

  • 是的,这是一项功能,已添加 Java7:Xrender pipeline now in JDK7 master

    另见 Enhancements in Java SE 7

  • 和 Java8,现在默认启用:Java8: Xrender Java2D pipeline enabled by default

    根据此博客的评论,XRender 管道仅与 Java2D、AWT 和 Swing 相关 - 其​​他 GUI 框架(JavaFX、SWT 等)无关受影响:

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

    我在发行说明中没有找到任何内容,但在源代码中,很明显,默认情况下启用了 XRender 管道:sun/awt/X11GraphicsEnvironment.java commit that changed this, was done already in 2011, according to the ticket 它始终与第一个 jdk8 版本一起发布。 我想,我之前没有遇到这个错误的原因是,我可能使用 java7 作为运行时间很长,而 eclipse 不受影响。

再次仔细查看重复的错误报告,已经有一个与堆栈跟踪匹配:

它是 bug JDK-8133723: sun.awt.image.BufImgSurfaceData 无法投射到太阳。java2d.xr.XRSurfaceData - 它真的不是重复的... 但是,重现此错误可能很困难。它仅在挂起到 RAM 周期后出现。

更新 1 - 触发器

该错误是通过使用 xrandr 更改输出显示触发的,例如

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

将立即引发 ClassCastException。当我在挂起之前关闭显示器时,我假设是挂起-恢复导致的,但这是错误的。

更新 2 - 新 Java 漏洞票

现在有一个新的 java 故障单:JDK-8160328

更新 3 - 修复了 jdk-9-ea-b131

故障单 JDK-8160328 已作为 JDK-8147542 的副本关闭 - 这个已用 修复java 9 的最新 EA 版本(版本 131 及更高版本)。

我可以确认,在使用 xrandr 切换监视器时我不再收到 ClassCastException。