问题 我如何解决java2d中的ClassCastException(Bug-ID 7172749)


我有幸遭遇java8中的错误, 对于其他任何人来说,这似乎不是一个大问题,因此Oracle不会在java9之前修复它。
这个bug有 错误ID 7172749 (还要注意相关和重复的错误) 它刚刚发生 每时每刻 在某台Linux机器上。
我在使用jdk1.8.0_u66的Ubuntu 14.04.3 LTS上遇到了问题。
但是,在Ubuntu 12.04.3和LTS的另一个盒子上 相同 JDK版本,我无法重现这个问题。

让我感到困惑的是,对于其他任何人来说,这似乎并不是一个显而易见的事情,所以我想也许我正在犯一个特别的转储错误。 我正在运行Oracle-JDK(而不是OpenJDK),因为我们的客户使用相同的版本(尽管在Windows上)并且想法是接近他们的环境。

所以,我的问题是,如何解决这个问题(例如,安装X11-library xy,使用magic -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)
[...]


10426
2017-12-09 20:37


起源

我怀疑,它还与我们在软件的某些领域仍然存在的一些尴尬的遗留编码风格有关...顺便说一下,问题也出现在OpenJDK 1.8.0_45中。 - tobi42
问题发生在icewm上。我们的管理员刚刚安装了xfce4,当我用xfce4作为窗口管理器运行时,我无法重现问题...我今天会测试一下,如果它有效,我将把它作为我的答案添加。 。 - tobi42
后续行动:Class-Cast异常现在也已经消失了。我猜想安装xfce4导致一些x11库更新......或者其他什么。 - tobi42
问题是,现在我在之前获得CCE的同一个窗口显然没有响应,好像它没有正确重新绘制...所以,我的简历是:“如何解决这个问题”=>现代化该代码,检查例如我们是否覆盖某些方法(未申报,甚至可能偶然)或对某些功能进行非常“创造性”的使用。 - tobi42
哦,我觉得我是全世界唯一一个有这种眩晕演员例外的人......这个bug被我忽略了2年,只是不知道该怎么办 - AvrDragon


答案:


我想出了一个 解决方法 对于这个问题。

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

有了这个选项,我再也没有看到问题了。

背景资料

错误JDK-7172749 现在最近已经修复了jdk9 build 124并且bugfix已经通过后向移植了 JDK-8158068 到jdk8更新112.您可以从这里下载jdk8u112构建预览: JDK8早期版本

但是,运行此构建并没有解决我的问题。

我的情况,我遇到了错误:我正在运行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)

此异常的效果是,jEdit或部件的整个窗口未绘制并保持白色。

看着 后端错误修复的补丁,它实际上修复了一个不同类的ClassCastException,即in sun.java2d.xr.XRRenderer

所以,这并不令人惊讶,这并没有解决我的问题。

另一个谷歌搜索透露 错误JDK-6975408 这让我意识到系统属性 sun.java2d.xrender

更多搜索:

  • 此选项在中描述 Java 2D技术的系统属性

    引用:

    XRENDER

    有可能的使用: 为现代基于X11的桌面启用基于XRender的Java 2D渲染管道,提供改进的图形性能。

    介绍: Java SE 7

    默认值: 假

    如何使用: 默认情况下禁用管道,但可以通过设置命令行属性来启用管道 -Dsun.java2d.xrender=true。较旧的X11配置可能无法支持XRender。冗长的形式, -Dsun.java2d.xrender=True,可用于启用消息到stdout,指示管道是否实际启用。

  • 是的,这是一个功能,已添加Java7: Xrender管道现在在JDK7 master中

    也可以看看 Java SE 7中的增强功能

  • 使用Java8,它现在默认启用: Java8:默认情况下启用Xrender Java2D管道

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

    基于Swing / AWT的应用程序应该受益,SWT / JavaFX / lwjgl / jogl使用与Java2D无关的其他代码路径。

    我没有在发行说明中找到任何内容,但在源代码中,很明显,XRender管道默认启用: 太阳/ AWT / X11GraphicsEnvironment.java承诺 改变了这种情况,已经在2011年完成了  它始终与第一个jdk8版本一起发布。 我想,我之前没有遇到过这个bug的原因是,我可能使用java7作为运行时间很长而且eclipse不受影响。

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

它的 错误JDK-8133723:sun.awt.image.BufImgSurfaceData无法强制转换为sun.java2d.xr.XRSurfaceData - 它真的不是重复的...... 但是,重现此错误可能很困难。它只在暂停到RAM周期后出现。

更新1 - 触发器

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

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

将立即导致ClassCastException。当我在暂停之前插上我的显示器时,我认为,这是暂停 - 恢复造成这种情况,但这是错误的。

更新2 - 新的Java Bug票证

现在有一个新的java bug票证: JDK-8160328

更新3 - 使用jdk-9-ea-b131修复

错误票 JDK-8160328 已被关闭作为副本 JDK-8147542  - 这个已经修好了 针对java 9的最新EA构建 (建立131及以后)。

我可以确认,当用xrandr切换监视器时,我不再获得ClassCastException。


14
2018-06-26 13:00



非常感谢分享 - tobi42
我在Ubuntu下遇到了这个bug。我的客户端确实使用Windows。他们也可能会受到这个问题的困扰吗? - Jakob Alexander Eichler
@tokam我不这么认为。该bug非常特定于linux / solaris实现(例如,使用 xrender库) - adangel
谢谢。它似乎在我的工作。当PC上运行java应用程序而电视机开启时,我总是遇到此错误,该电视机通过HDMI连接到PC。我用linux。 - ka3ak
如果你是因为来到这里的 Netbeans Bug#219756,你可以通过包括解决它 -J-Dsun.java2d.xrender=false 在你的 $NETBEANS_HOME/etc/netbeans.conf 作为一部分 netbeans_default_options。 - stiemannkj1