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

时间:2015-12-09 20:37:08

标签: java linux java-8 awt java-2d

我有幸遭遇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,使用魔法-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)
[...]

1 个答案:

答案 0 :(得分:14)

我找到了问题的解决方法

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

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

背景资料

Bug JDK-7172749最近已使用jdk9 build 124修复,并且错误修正已通过JDK-8158068反向移植到jdk8更新112.您可以从此处下载jdk8u112构建预览: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)

这个例外的影响是,jEdit或零件的整个窗口都没有被绘制并保持白色。

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

所以,这并不令我感到惊讶,因为这并没有解决我的问题。

另一个谷歌搜索显示bug JDK-6975408让我意识到系统属性sun.java2d.xrender

更多搜索:

  • System Properties for Java 2D Technology

    中介绍了此选项

    引用:

      

    <强> XRENDER

         

    预期用途:为现代基于X11的桌面启用基于XRender的Java 2D渲染管道,提供更高的图形性能。

         

    介绍: Java SE 7

         

    默认值: false

         

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

  • 是的,它是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的应用程序应该受益,SWT / JavaFX / lwjgl / jogl使用与Java2D无关的其他代码路径。

    我在发行说明中找不到任何内容,但在源代码中,显而易见的是,XRender管道默认启用:sun/awt/X11GraphicsEnvironment.java 改变了这一点的commit已于2011年完成,根据ticket它始终在第一个jdk8版本上发布。 我想,我之前没有遇到过这个错误的原因是,我可能使用java7作为运行时间很长而且日食不受影响。

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

它的bug 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 Ticket

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

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

修复

错误提单JDK-8160328已被关闭为JDK-8147542的副本 - 此问题已通过latest EA build for java 9(修订版131及更高版本)修复。

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