Этот ответ записывает то, что я нашел до сих пор. Если у кого-то есть дополнительная информация, пожалуйста, прокомментируйте или оставьте ответ. Я не совсем доволен простым отключением Swing от D3D и открыт для других решений.
Причина: инициализация D3D
Swing использует Java2D API для рисования, и в соответствии с этим Руководством по устранению неполадок Java SE 7 , Java2D использует набор конвейеров рендеринга, «который можно грубо определить как различные способы рендеринга примитивов». В частности, конвейер рендеринга Java2D, похоже, соединяет кроссплатформенный код Java с собственными графическими библиотеками (OpenGL, X11, D3D, DirectDraw, GDI), которые могут поддерживать аппаратное ускорение.
В Java 1.6.0_10 (он же 6u10) , «полностью аппаратно ускоренный графический конвейер» на основе Direct3D был добавлен в Java2D для Windows для повышения производительности рендеринга в приложениях Swing и Java2D (по умолчанию включено) .
По умолчанию, когда Java2D используется в системе Windows, этот конвейер Direct3D и конвейер DirectDraw / GDI включены по умолчанию (я предполагаю, что каждый из них используется для разных целей).
Библиотека D3D, по крайней мере, загружается и инициализируется только при необходимости, а встроенная функция инициализации D3D, которая вызывается при первом создании Window (или потомка Window), занимает ~ 500 мс (для меня) и вызывает сообщается о медленной инициализации и отключении конвейера D3D, по-видимому, удаляет вызов этой встроенной функции, значительно сокращая время запуска. (Хотя я бы предпочел отложить, предварительно вычислить, поделиться (через разные java-приложения) или оптимизировать инициализацию D3D, и мне интересно, будет ли это медленно для других языков.)
Конечно, возможно, что на большинстве систем время, затрачиваемое на инициализацию D3D, незначительно, и это проблема только в моей системе из-за проблем с оборудованием или драйвером, но я несколько скептически отношусь к этому (хотя, если это правда , это было бы легко исправить).
Детализация трассировки до собственного initD3D ()
Более подробно (пропустите следующий абзац, если вам все равно), я использовал профилировщик и отладчик Netbeans, чтобы найти:
Когда JFrame инициализируется (вызывается конструктор), вызывается конструктор класса предка java.awt.Window. Окно инициализирует свое устройство GraphicsConfiguration, которое пытается извлечь устройство экрана по умолчанию и так далее. В первый раз, когда это происходит (когда инициализируется первый Window или Window потомок), экранное устройство не существует, поэтому оно создается. В этом процессе класс sun.java2D.d3d.D3DGraphicsDevice инициализируется, и в своем статическом блоке инициализации (см. () ) он вызывает встроенную функцию initD3D (), которая занимает значительное время выполнения (~ 500 мс).
Мне удалось найти версию исходного кода для D3DGraphicsDevice и его статического блока инициализации (и я на самом деле просто предполагаю, что initD3D () - это то, что делает его ( ) так долго - мой профилировщик, похоже, не распознает нативные функции - но это разумное предположение).
Один обходной путь - отключить D3D для Java2D
Конвейер D3D можно отключить, запустив java с опцией -Dsun.java2d.d3d=false
, согласно этому руководству по Java2D "системные свойства" (а также вышеупомянутому руководству по устранению неполадок ). Я думаю, что это отключает D3D, но не DirectDraw, который можно отключить с помощью Dsun.java2d.noddraw=true
(и тогда «все операции будут выполняться с GDI»), но это не заметно улучшит время инициализации.
Например, я мог бы использовать команду вроде следующей для запуска MyJar.jar без D3D:
java -jar -Dsun.java2d.d3d=false MyJar.jar
С кодом, размещенным в вопросе (который инициализирует Window, а затем 2 объекта JFrame), я получаю результаты, подобные этому:
0 for first Window
47 for first JFrame.
0 for second JFrame.
Вместо результатов, подобных этому:
547 for first Window
31 for first JFrame.
0 for second JFrame.
(Обратите внимание, что время указывается в миллисекундах и измеряется с помощью System.currentTimeMillis () в Windows, разрешение которого, я думаю, составляет от 15 до 16 мс.)
OpenGL против Direct3D
OpenGL используется вместо Direct3D, если используется опция -Dsun.java2d.opengl=True
. В моей системе есть небольшое улучшение (~ 400 мс для OpenGL против ~ 500 мс для D3D), но задержка все еще заметна.
Другие задержки
Я заметил, что инициализация первого объекта JFrame, даже если это не первое Окно, занимает намного больше времени, чем инициализация последующих объектов JFrame (записывается как 31–47 мс против 0 мс).
Профилирование указывает, что это связано с созданием первой стеклянной панели (JPanel), и в конечном счете, похоже, что оно вызвано Look and Feel и инициализацией / загрузкой системных свойств внутри класса javax.swing.UIManager и кода инициализации объекта. Это не слишком важно, но объясняет наблюдаемую аномалию.
В моей реальной программе, которая немного сложнее (должна инициализировать больше компонентов Swing), задержки кажутся более диффузно распределенными в коде Swing, но я заметил значительную загрузку нативных классов ", установка UI "(загрузка свойств пользовательского интерфейса по умолчанию и т. д.) и тому подобное. К сожалению, я не думаю, что с этим можно что-то сделать (говорите, если есть).
Заключительные мысли
В конце концов, многое можно сделать, и я должен понять, как далеко зашли Swing и JVM за последние годы.