Swing, исключение удаленного рабочего стола

Мое приложение Swing выдает ArrayIndexOutOfBounds исключений, когда я использую удаленный рабочий стол Windows для подключения к ПК, на котором запущено мое приложение. Любая идея, что может быть причиной этого?

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3
    at sun.awt.Win32GraphicsEnvironment.getDefaultScreenDevice(Win32GraphicsEnvironment.java:96)
    at sun.awt.windows.WWindowPeer.updateGC(WWindowPeer.java:470)
    at sun.awt.windows.WWindowPeer.displayChanged(WWindowPeer.java:508)
    at sun.awt.windows.WWindowPeer$1.run(WWindowPeer.java:448)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:708)
    at java.awt.EventQueue$4.run(EventQueue.java:706)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

Я видел это дважды при удаленном подключении к ПК, но никогда не видел этого в других ситуациях. Поскольку все это является внутренним для Java 7u25 Sun JDK (посмотрите на трассировку стека ниже), я даже не знаю, как это отлаживать. Мысли?


Другая информация. В машине установлены две видеокарты с двумя портами для мониторов на каждой, а Windows настроена на включение всех четырех мониторов. Однако, когда я подключаюсь к машине, очевидно, есть только 1 монитор. Монитор с меню «Пуск» (и монитор, содержащий приложение) идентифицируется Windows как монитор №4.

System.getProperties().list(System.out);:

-- listing properties --
java.runtime.name=Java(TM) SE Runtime Environment
sun.boot.library.path=D:\Program Files\Java\jdk1.7.0_25\jre...
java.vm.version=23.25-b01
java.vm.vendor=Oracle Corporation
java.vendor.url=http://java.oracle.com/
path.separator=;
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg=sun.io
user.script=
user.country=US
sun.java.launcher=SUN_STANDARD
sun.os.patch.level=Service Pack 1
java.vm.specification.name=Java Virtual Machine Specification
user.dir=C:\Code\workspace\client
java.runtime.version=1.7.0_25-b16
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs=D:\Program Files\Java\jdk1.7.0_25\jre...
os.arch=amd64
java.io.tmpdir=XXXXXXXXXXXXXXXXXXXXXXXXXXXX
line.separator=

java.vm.specification.vendor=Oracle Corporation
user.variant=
os.name=Windows 7
sun.jnu.encoding=Cp1252
java.library.path=D:\Program Files\Java\jdk1.7.0_25\bin...
java.specification.name=Java Platform API Specification
java.class.version=51.0
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
os.version=6.1
user.home=XXXXXXXXXXXXXXXXXXXXXXXXX
user.timezone=
java.awt.printerjob=sun.awt.windows.WPrinterJob
file.encoding=Cp1252
java.specification.version=1.7
user.name=XXXXXXXXXXXXXXXXXXXXXXXXX
java.class.path=C:\Code\workspace\client\target\class...
java.vm.specification.version=1.7
sun.arch.data.model=64
java.home=D:\Program Files\Java\jdk1.7.0_25\jre
sun.java.command=com.techemet.client.ClientMain
java.specification.vendor=Oracle Corporation
user.language=en
awt.toolkit=sun.awt.windows.WToolkit
java.vm.info=mixed mode
java.version=1.7.0_25
java.ext.dirs=D:\Program Files\Java\jdk1.7.0_25\jre...
sun.boot.class.path=D:\Program Files\Java\jdk1.7.0_25\jre...
java.vendor=Oracle Corporation
file.separator=\
java.vendor.url.bug=http://bugreport.sun.com/bugreport/
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.desktop=windows
sun.cpu.isalist=amd64

person durron597    schedule 14.10.2013    source источник
comment
звучит как ошибка jvm для меня. а через VNC пробовали?   -  person    schedule 14.10.2013
comment
@user2511414 user2511414 Нет, мне стыдно признаться, что я спросил здесь, прежде чем сильно пытаться.   -  person durron597    schedule 15.10.2013
comment
Вы пытались обновить графический драйвер до последней версии на этом компьютере?   -  person MicSim    schedule 28.10.2013
comment
@MicSim сейчас попробую   -  person durron597    schedule 28.10.2013
comment
Также см. эту закрытую ошибку JDK (bugs.sun.com/view_bug.do?bug_id=4923108) и связанные с ними ошибки для поиска проблемы.   -  person MicSim    schedule 28.10.2013
comment
@MicSim очарователен. Обратите внимание, что ваша связанная ошибка была закрыта как дубликат этой ошибки, т.е. должно быть исправлено с 7u8. Обратите внимание, что я использую 7u25.   -  person durron597    schedule 28.10.2013


Ответы (1)


Документ Sun для ошибки JDK-4417798 (той, которую вы упомянули в своем последнем комментарии) описывает способ перехвата исключения. Цитата из документа:

public class BugHandler {
    public void handle(Throwable throwable) {
        if (e instanceof ArrayIndexOutOfBoundsException) {
           StackTraceElement[] trace = e.getStackTrace();

           if (trace.length > 1 
               && trace[0].getClassName().equals("sun.awt.Win32GraphicsEnvironment")
               && trace[0].getMethodName().equals("getDefaultScreenDevice")) {
              your_code_to_handle_exception();               
           }
        } 
    }
}

Также предлагается установить для параметра -Dsun.java2d.noddraw значение true. Согласно этому другому документу, он запрещает использование DirectDraw и Direct3D. Посмотрите, поможет ли это.

Вы также можете попытаться заставить приложение работать на определенном экране вместо того, чтобы полагаться на автоматическое определение графической среды Java. Существует соответствующий пример использования класса GraphicsDevice в Документация по API.

person HQCasanova    schedule 31.10.2013
comment
Хорошая попытка, но их исправление гораздо более инвазивно, чем только этот класс. Если вы прокрутите несколько строк вверх: для того, чтобы этот обходной путь работал, вам понадобятся следующие 4 класса. Вам также потребуется преобразовать все JFrames и JDialog в IFrame или IDialog (все подклассы И экземпляры), а также необходимо зарегистрировать BugHandler в качестве обработчика исключений по умолчанию. Хотя технически это решение, это в значительной степени последнее средство устранения неполадок. - person durron597; 01.11.2013
comment
@ durron597 Спасибо за комментарий. Да, именно поэтому я включил выше только одну часть этого обходного пути. Я знал, что реализация всего этого будет излишним. Поскольку вы упомянули, что хотите, по крайней мере, иметь возможность перехватывать исключение, я подумал, что привлечение вашего внимания к этой части кода может быть полезно для вас и других. Longshot, но вы пробовали вариант noddraw? А как насчет принудительного запуска приложения на определенном экране? Это вариант? Спасибо еще раз. - person HQCasanova; 01.11.2013
comment
Отключение прямого рисования кажется горячим предложением, потому что удаленный рабочий стол часто не работает при попытке использовать аппаратное ускорение. - person PMF; 02.11.2013