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

2022-03-11 00:00:00 linux java-8 java awt java-2d

我很倒霉,因为我在java8中遇到了一个错误, 对于其他任何人来说,这似乎都不是什么大问题,因此Oracle不会在java9之前修复它。
错误具有Bug-ID 7172749(还请注意相关和重复的错误) 在某个Linux机器上,它总是经常发生。
我在带有jdk1.8.0_u66的Ubuntu 14.04.3 LTS上遇到了这个问题。
但是,在另一个安装了Ubuntu12.04.3LTS和相同的JDK版本的机器上,我根本无法重现这个问题。

让我迷惑不解的是,这似乎并没有给其他任何人带来惊喜,所以我猜我可能犯了一个特别严重的错误。 我运行的是Oracle-JDK(与OpenJDK相反),因为我们的客户使用相同的版本(尽管是在Windows上),并且我们的想法是接近他们的环境。

所以,我的问题是,如何绕过这个问题(例如,安装X11库XY,使用Magic-XXjava2dailsafe参数启动我的java程序,或者类似的东西)
并加入到可以放心地等待甲骨文解决实际问题的人群中吗?

致以最诚挚的问候 TOBI

顺便说一下,我的堆栈如下所示:

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最近已使用jdk9内部版本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,它实际上修复了不同类(即sun.java2d.xr.XRRenderer)中的ClassCastException。

所以,这没有解决我的问题也就不足为奇了。

另一次Google搜索显示bug JDK-6975408,这使我意识到系统属性sun.java2d.xrender

更多搜索:

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

    中介绍

    报价:

    xender

    目标用途:为基于X11的现代台式机启用基于XRender的Java 2D呈现管道,提供更高的图形性能。

    介绍:Java SE 7

    默认值:false

    使用方法:管道默认禁用,但可以通过设置命令行属性-Dsun.java2d.xrender=true启用。较早的X11配置可能无法支持XRender。详细形式-Dsun.java2d.xrender=True可用于将消息启用到标准输出,指示管道是否已实际启用。

  • 是的,这是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 改变了这一点的已经在2011年完成了,根据第一个jdk8版本的说法,它一直都是启用的。([3-11]>在2011年已经完成了,根据ticket的说法,它总是在第一个jdk8版本中启用。 我想,我之前没有经历过这个错误的原因是,我可能将java7作为运行时使用了相当长的时间,并且Eclipse没有受到影响。

    /li>

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

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错误票证

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

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

错误票证JDK-8160328已作为JDK-8147542的副本关闭-此错误票证已使用latest EA build for java 9(内部版本131及更高版本)修复。

我可以确认,使用xrandr切换显示器时不再出现ClassCastException。

相关文章