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

2022-09-04 20:52:15

我很幸运地遭受了java8中的错误,这对其他人来说似乎不是一个大问题,所以Oracle不会在java9之前修复它。
该错误具有错误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程序,或者沿着这些路线)
加入那些可以舒适地等待预言机修复实际问题的人群?

最好的问候托比

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

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

我为这个问题找到了解决方法

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

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

背景信息

Bug JDK-7172749 最近已在 jdk9 build 124 中得到修复,并且 Bug 修复已通过 JDK-8158068 向后移植到 jdk8 更新 112。你可以从这里下载 jdk8u112 内部版本预览版:JDK8 抢先体验版

但是,运行此版本并没有为我解决问题。

我的情况是,我遇到错误:我正在运行jEdit,并且在我将Linux从挂起恢复到RAM后看到这些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,即.sun.java2d.xr.XRRenderer

因此,这并没有解决我的问题。

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

更多搜索:

  • Java 2D 技术的系统属性中介绍了此选项

    报价:

    xrender

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

    介绍:Java SE 7

    默认值:

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

  • 是的,这是一个功能,已经与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管道默认处于启用状态:sun/awt/X11GraphicsEnvironment.java改变这一点的提交已经在2011年完成,根据第一个jdk8版本的票证,它始终处于打开状态。我想,我之前没有遇到过这个错误的原因是,我可能使用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 错误票证

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

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

错误票证 JDK-8160328 已作为 JDK-8147542 的副本关闭 - 此错误已通过 java 9 的最新 EA 版本(内部版本 131 及更高版本)修复。

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


答案 2

推荐