我已经追踪到这是由java.awt.Window类的构造函数引起的,该类是JFrame的祖先类。
奇怪的是,该构造函数仅对第一次调用较慢。如果我创建多个JFrame对象,则构造函数中花费的时间对于第一个对象约为600ms,但通常被测量为后续对象的0ms。
以下是一个简单的示例,在我的系统上,第一个构造函数调用显示了显着的延迟,但第二个构造函数没有。
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.");
}
});
}
典型输出为:
641 for first JFrame.
0 for second JFrame.
如果我在JFrame对象之前添加此窗口对象初始化代码:
java.awt.Window window = new java.awt.Window(null);
然后输出结果会变成类似以下的内容:
578 for first Window.
47 for first JFrame.
0 for second JFrame.
当我尝试使用Window的超类java.awt.Container时,Window构造函数仍然需要很长时间才能执行(因此问题并没有超出Window类)。
由于JFrame构造函数调用了Window构造函数,上述情况似乎表明第一次调用Window构造函数是昂贵的。
第一次调用构造函数会发生什么事情,有没有什么我可以做来解决这个问题?是否存在一些简单的修复方法,或者这个问题是Swing/AWT固有的问题?或者这可能是我的系统/设置特定的问题吗?
我希望我的应用程序能够像MS记事本一样快速打开(或者几乎一样快),虽然如果我将代码放在第一个JFrame初始化之前,可以在Notepad打开时在控制台上打印文本,但上述问题意味着窗口可见之前几乎有一秒钟的延迟。我需要使用不同的语言或GUI框架来获得所需的性能吗?
编辑:如果我将Thread.sleep(10000)作为run()的第一行添加,结果不会改变(它们只是晚了10秒出现)。这表明问题不是由一些异步启动代码引起的,而是直接由构造函数调用触发的。
编辑2:意识到NetBeans Profiler可以在JRE类内部进行分析,并发现大部分时间都花费在初始化sun.java2d.d3d.D3DGraphicsDevice对象上(Window对象需要屏幕边界和插图),它是Java 6u10引入的“默认启用的Microsoft Windows平台的Direct3D加速渲染管道”的一部分。可以通过将“-Dsun.java2d.d3d=false”属性传递给JVM来禁用它,这确实将启动时间缩短了约3/4,但我还不确定是否需要它(D3D)或者是否有其他方法可以让它加载更快。 如果我在命令行上放置该参数,则输出如下:
0 for first Window
47 for first JFrame.
0 for second JFrame.
我稍后会深入了解后回来整理这篇文章。