我想出了一个解决方法对于这个问题。
简而言之:使用参数启动 JVM-Dsun.java2d.xrender=false
.
有了这个选项,我就不再看到问题了。
背景信息
The 错误 JDK-7172749 https://bugs.openjdk.java.net/browse/JDK-7172749最近已使用 jdk9 build 124 进行了修复,并且该错误修复已通过向后移植JDK-8158068 https://bugs.openjdk.java.net/browse/JDK-8158068到 jdk8 更新 112。您可以从这里下载 jdk8u112 构建预览:JDK8 早期访问版本 https://jdk8.java.net/download.html.
然而,运行这个构建并没有解决我的问题。
我的情况,我遇到了这个错误:我正在运行 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 的整个窗口或部分窗口不会绘制并保持白色。
看着向后移植的错误修复补丁 http://hg.openjdk.java.net/jdk8u/jdk8u-dev/jdk/rev/907689a62eab,它实际上修复了另一个类中的 ClassCastException,即sun.java2d.xr.XRRenderer
.
因此,这并没有解决我的问题也就不足为奇了。
另一个谷歌搜索显示错误 JDK-6975408 https://bugs.openjdk.java.net/browse/JDK-6975408这让我意识到了系统属性sun.java2d.xrender
.
更多搜索:
-
该选项的描述见Java 2D 技术的系统属性 https://docs.oracle.com/javase/8/docs/technotes/guides/2d/flags.html#xrender
Quote:
xrender
有可能的使用:为基于 X11 的现代桌面启用基于 XRender 的 Java 2D 渲染管道,从而提供改进的图形性能。
介绍:Java SE 7
默认值: false
如何使用:默认情况下禁用管道,但可以通过设置命令行属性来启用-Dsun.java2d.xrender=true
。较旧的 X11 配置可能无法支持 XRender。冗长的形式,-Dsun.java2d.xrender=True
,可用于向标准输出启用一条消息,指示管道是否实际已启用。
-
是的,这是 Java7 中添加的一个功能:Xrender 管道现在位于 JDK7 master 中 http://linuxhippy.blogspot.de/2010/06/xrender-pipeline-now-in-jdk7-master.html
也可以看看Java SE 7 中的增强功能 https://docs.oracle.com/javase/8/docs/technotes/guides/2d/enhancements70.html
-
对于 Java8,现在默认启用它:Java8:默认启用 Xrender Java2D 管道 http://linuxhippy.blogspot.de/2014/03/java8-xrender-java2d-pipeline-enabled.html
根据此博客的评论,XRender 管道仅与 Java2D、AWT 和 Swing 相关 - 其他 GUI 框架(JavaFX、SWT...)不受影响:
基于 Swing/AWT 的应用程序应该会受益,SWT/JavaFX/lwjgl/jogl 使用与 Java2D 不相关的其他代码路径。
我在发行说明中没有找到任何内容,但在源代码中,很明显,默认情况下启用了 XRender 管道:sun/awt/X11GraphicsEnvironment.java http://hg.openjdk.java.net/jdk8u/jdk8u-dev/jdk/file/b44d695f738b/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java
The commit http://hg.openjdk.java.net/jdk8u/jdk8u-dev/jdk/rev/6664b47ddfd9根据ticket https://bugs.openjdk.java.net/browse/JDK-7077423它总是在第一个 jdk8 版本中出现。
我想,我之前没有遇到这个错误的原因是,我可能使用 java7 作为运行时很长一段时间,并且 eclipse 不受影响。
再次仔细查看重复的错误报告,已经有一个与堆栈跟踪相匹配:
It's 错误 JDK-8133723 https://bugs.openjdk.java.net/browse/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 bug 票证:JDK-8160328 https://bugs.openjdk.java.net/browse/JDK-8160328
更新 3 - 使用 jdk-9-ea-b131 修复
错误票JDK-8160328 https://bugs.openjdk.java.net/browse/JDK-8160328已作为以下重复项被关闭JDK-8147542 https://bugs.openjdk.java.net/browse/JDK-8147542- 这个已经被修复了java 9 的最新 EA 版本 https://jdk9.java.net/download/(版本 131 及更高版本)。
我可以确认,使用 xrandr 切换监视器时不再出现 ClassCastException。