Как я могу обойти ClassCastException в java2d (Bug-ID 7172749)

Мне повезло, что я страдал от ошибки в java8, это не кажется большой проблемой для кого-либо еще, поэтому Oracle не собирается исправлять его до java9.
У ошибки был Bug-ID 7172749 (также обратите внимание на связанные и дублированные ошибки) и это просто все время происходит на определенной машине Linux.
Я испытываю проблему на Ubuntu 14.04.3 LTS с jdk1.8.0_u66.
Однако в другой коробке с Ubuntu 12.04.3 LTS и той же версией JDK я не могу воспроизвести проблему вообще.

Меня озадачивает то, что это не похоже на демонстрацию для кого-либо еще, поэтому я думаю, что, возможно, я делаю особенно неудачную ошибку. Я запускаю Oracle-JDK (в отличие от OpenJDK), потому что наш клиент использует ту же версию (хотя и в Windows), и идея должна быть близка к их среде.

Итак, мой вопрос: как обойти эту проблему (например, установить X11-библиотеку xy, запустить мою java-программу с помощью волшебного параметра -XXjava2dfailsafe или sth вдоль этих строк)
и присоединиться к стаду людей, которые могут с комфортом ждать, пока проблема будет исправлена ​​оракулом?

С уважением Tobi

Btw, мой стек выглядит так:

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.

С этой опцией я больше не видел проблемы.

Фоновая информация

Ошибка JDK-7172749 теперь исправлена ​​с помощью jdk9 build 124 и исправлено багфинг через JDK-8158068 в jdk8 update 112. Вы можете скачать предварительный просмотр сборки jdk8u112 здесь: JDK8 Early Access Releases.

Однако запуск этой сборки не помог мне решить.

В моей ситуации, когда я испытываю ошибку: я запускаю jEdit, и я вижу это ClassCastException после того, как я возобновляю свой Linux из suspend-to-RAM. Это та же самая стек:

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.

Итак, это не удивительно, что это не устранило мою проблему.

В другом поиске Google обнаружена ошибка ошибка JDK-6975408, которая сообщила мне о системном свойстве sun.java2d.xrender.

Дополнительная информация:

  • Эта опция описана в Свойства системы для Java 2D технологии

    Цитата:

    XRender

    Предполагаемое использование: Чтобы включить построение Java 2D-рендеринга на основе XRender для современных настольных компьютеров на базе X11, предлагая улучшенную производительность графики.

    Представлено: Java SE 7

    Значение по умолчанию: false

    Как использовать: Конвейер отключен по умолчанию, но может быть включен, установив свойство командной строки -Dsun.java2d.xrender=true. Более старые конфигурации X11, возможно, не смогут поддерживать XRender. Подробную форму -Dsun.java2d.xrender=true можно использовать для включения сообщения в стандартный вывод, указывающий, действительно ли был включен конвейер.

  • Да, это функция, добавленная с Java7: Xrender-конвейер теперь в главном JDK7

    См. также Улучшения в 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 commit, который изменил это, был сделан уже в 2011 году, согласно билету он всегда был включен в первый выпуск jdk8. По-моему, причина, по которой я раньше не испытывал эту ошибку, заключается в том, что я, вероятно, использовал java7 в качестве среды выполнения довольно долго, и затмение не затрагивается.

После более подробного просмотра дублированных отчетов об ошибках уже есть один, который будет соответствовать stacktrace:

Это ошибка 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: JDK-8160328

Обновление 3 - Исправлено с помощью jdk-9-ea-b131

Билет ошибки JDK-8160328 был закрыт как дубликат JDK-8147542 - и этот был исправлен с помощью последней сборки EA для java 9 (сборка 131 и позже).

Я мог бы подтвердить, что я больше не получаю ClassCastException при переключении мониторов с помощью xrandr.