Ответ 1
Этот ответ записывает то, что я нашел до сих пор. Если у кого-то есть дополнительная информация, прокомментируйте или отправьте ответ. Я не полностью удовлетворен просто отключением использования Swing D3D, и я открыт для других решений.
Причина: инициализация D3D
Swing использует Java2D API для рисования, и в соответствии с этим Руководство по поиску и устранению неисправностей Java SE 7, Java2D использует набор конвейеров рендеринга ", могут быть грубо определены как разные способы рендеринга примитивов". Более конкретно, конвейер рендеринга Java2D, по-видимому, связывает межплатформенный Java-код с собственными графическими библиотеками (OpenGL, X11, D3D, DirectDraw, GDI), которые могут поддерживать аппаратное ускорение.
В Java 1.6.0_10 (aka 6u10) в Java2D для Windows был добавлен "полностью аппаратный ускоренный графический конвейер" на основе Direct3D улучшить производительность рендеринга в приложениях Swing и Java2D (по умолчанию включено).
По умолчанию, когда Java2D используется в системе Windows, и этот конвейер Direct3D, и конвейер DirectDraw/GDI по умолчанию включены (я предполагаю, что они используются для разных вещей).
Библиотека D3D, по крайней мере, загружается и инициализируется, когда это необходимо, и встроенная функция инициализации D3D, которая вызывается при первом создании окна (или потомка окна), занимает ~ 500 мс (для меня) и вызывает сообщила о медленности инициализации, и отключение D3D-конвейера, кажется, устраняет вызов этой нативной функции, что значительно сокращает время запуска. (Хотя я бы предпочел задерживать, прекомпетровать, делиться (в разных приложениях Java) или оптимизировать инициализацию D3D, и мне интересно, не слишком ли это для других языков.)
Конечно, возможно, что в большинстве систем время, проведенное в D3D init, незначительно, и это только проблема в моей системе из-за некоторых проблем с оборудованием или драйвером, но я несколько скептически отношусь к этому (хотя, если true, это было бы легко исправить).
Детализация трассировки до исходного initD3D()
Более подробно (пропустите следующий абзац, если вам все равно), я использовал профилировщик и отладчик Netbeans, чтобы найти следующее:
Когда инициализируется JFrame (вызванный конструктор), вызывается конструктор класса предка java.awt.Window. Окно инициализирует свое устройство GraphicsConfiguration, которое пытается извлечь экранное устройство по умолчанию и так далее. В первый раз, когда это происходит (когда первый оконный или оконный потомок инициализируется), экранное устройство не существует, поэтому оно построено. В этом процессе класс sun.java2D.d3d.D3DGraphicsDevice инициализируется и в своем статическом блоке инициализации (см. <clinit> ()) он вызывает встроенную функцию initD3D(), которая занимает значительное время для выполнения (~ 500 мс).
Мне удалось найти версию исходного кода для D3DGraphicsDevice и ее статический блок init (и я действительно просто предполагаю из этого источник, что initD3D() делает его <clinit> () так долго - мой профилировщик, похоже, не признает родные функции, но это разумное предположение).
Один обходной путь - отключить 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 vs 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, но я заметил значительный объем загрузки на родном классе, "установка пользовательского интерфейса" (загрузка свойств пользовательского интерфейса по умолчанию и т.д.) и т.д. К сожалению, я не думаю, что многое можно сделать по этому поводу (пожалуйста, сообщите, если есть).
Закрытие мысли
В конце концов, есть только так много, что можно сделать, и я должен узнать, как далеко зашли Swing и JVM за последние годы.