我正在尝试使用Java Swing构建一个简单,轻量级且响应迅速的应用程序。 然而,当它启动时,在窗口(JFrame)出现之前会有明显的延迟(> 500ms)。
我已将其跟踪到java.awt.Window类的构造函数,该类是JFrame的祖先。
奇怪的是,构造函数对第一次调用的速度很慢。如果我创建了多个JFrame对象,那么第一个对象在构造函数中花费的时间约为600毫秒,但后续对象的时间通常为0毫秒。
这是一个简单的例子,在我的系统中,显示第一个构造函数调用的显着延迟,但不是第二个:
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对象之前添加此Window对象初始化:
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 Notepad一样快(或几乎同样快)的速度打开,并且,虽然我可以在记事本打开时将文本打印到控制台(如果我在第一次JFrame初始化之前放置代码) ),上述问题意味着在窗口可见之前几乎有一整秒的延迟。我是否需要使用不同的语言或GUI框架来获得我追求的性能?
编辑:如果我将Thread.sleep(10000)添加为run()的第一行,则结果不会更改(它们仅在10秒后出现)。这表明问题不是由某些异步启动代码引起的,而是由构造函数调用直接触发。
编辑2 :实现了NetBeans Profiler可以在JRE类中进行概要分析,并发现大部分时间都花在初始化sun.java2d.d3d.D3DGraphicsDevice对象上(Window对象需要屏幕边界)和{insets),它是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.
在我稍后深入挖掘后,我会回来清理这篇文章。
答案 0 :(得分:9)
答案 1 :(得分:2)
第一个jframe的创建涉及加载swing库。 JVM不会加载库查看import语句。仅在第一次调用该库时才加载库。
在这种情况下,frame1创建是第一个调用Swing库的语句。在创建frame2实例时,已经加载了swing库,因此frame2的对象创建速度太快,甚至没有注意到一些时间的流逝。因此它显示为0.
这解释了为什么当你将Window语句加在两者之上时它显示578,47,0。这是因为第一个语句需要时间来加载java.awt库。第二个需要时间来加载swing库。并且三分之一显示为0,因为其创建所需的库已经加载。
您甚至可以通过这种方式进行测试。尝试用JPanel替换第二个JFrame创建,它仍显示为0.
答案 2 :(得分:1)
我的猜测是它正在加载本机库。如果是这种情况,那么你无能为力。
答案 3 :(得分:1)
Mac OS X 10.5.8,Java 1.6.0_26。考虑到JVM启动时间和重量级图形同伴创建,这并不意外。
247 for first JFrame. 0 for second JFrame.
附录:根据文章Java Performance: Startup time,您的平台上可能会提供Java Quick Starter。
答案 4 :(得分:1)
加载所有swing类需要时间,然后加载本机awt库需要时间。也许,类加载需要更多时间,因为如果你只是创建一个JLabel而不是第一个JFrame,它仍然需要更多的时间。