I'm trying to build a simple, lightweight, and responsive application using Java Swing. When it launches, however, there is a noticeable delay (>500ms) before the window (a JFrame) appears.
I've tracked it down to the constructor of the java.awt.Window class, which is an ancestor of JFrame.
Oddly, the constructor is only slow for the first call. If I create multiple JFrame objects, the time spent in the constructor is ~600ms for the first object, but is typically measured as 0ms for subsequent objects.
Here's a simple example which, on my system, shows this significant delay for the first constructor call but not the second:
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
long start;
start = System.currentTimeMillis();
JFrame frame1 = new JFrame();
System.out.println((System.currentTimeMillis() - start) + " for first JFrame.");
start = System.currentTimeMillis();
JFrame frame2 = new JFrame();
System.out.println((System.currentTimeMillis() - start) + " for second JFrame.");
}
});
}
With typical output:
641 for first JFrame.
0 for second JFrame.
If I add this Window object initialization before the JFrame objects:
java.awt.Window window = new java.awt.Window(null);
Then the output changes to something like:
578 for first Window.
47 for first JFrame.
0 for second JFrame.
When I try the same with the superclass of Window, java.awt.Container, the Window constructor is still the one that takes a long time to execute (so the problem doesn't go above the Window class).
Since the JFrame constructor calls the Window constructor, the above seems to indicate that the first call to the Window constructor is expensive.
What happens in the first call to the constructor that takes so long, and is there anything I can do about it? Is there some simple fix or is the problem fundamental to Swing/AWT? Or is it perhaps a problem specific to my system/setup?
I'd like my application to open as fast (or nearly as fast) as MS Notepad, and, while I can have text printed to the console around the time Notepad opens (if I put the code before the first JFrame initialization), the above problem means that there is almost a whole second of delay before the window is visible. Will I need to use a different language or GUI framework to get the performance I'm after?
Edit: If I add Thread.sleep(10000) as the first line of run(), the results don't change (they just appear 10 seconds later). This suggests that the problem is not caused by some asynchronous startup code but is instead triggered directly by the constructor call.
Edit 2: Realized the NetBeans Profiler can profile inside the JRE classes, and discovered that most of the time is spent initializing a sun.java2d.d3d.D3DGraphicsDevice object (the Window object needs screen bounds and insets), which is part of a "Direct3D Accelerated Rendering Pipeline for Microsoft Windows Platforms, Enabled by Default", introduced in Java 6u10. It can be disabled by passing the "-Dsun.java2d.d3d=false" property to the JVM, which does reduce the startup time by about 3/4, but I'm not yet sure if I'll need it (D3D) or if there's some other way to get it to load faster. Here is the output if I put that parameter on the command line:
0 for first Window
47 for first JFrame.
0 for second JFrame.
I'll come back and clean this post up after I dig deeper later.