如何减少 Java Swing 表单的加载时间?

4
在我的Swing应用程序中,当第一次创建一个新的Swing表单时,会出现几百毫秒的延迟问题。这并不是很长,但主观上感觉变慢真的很令人恼火。
这种情况发生在所有的表单中,甚至包括一个JOptionPane消息或其他简单的表单。(当然,由于构造函数更加复杂,更大的表单需要花费更长时间)
现在我注意到,第二次创建新的表单实例要快得多。
既然初始启动时间并不重要,我正在计划在启动时创建所有重要表单的不可见实例,但这看起来像是个脏的hack (并且我也不确定它是否能正常工作)。
我的问题:
1. 是否有更优雅的方法来加快表单的创建和显示速度?
2. 第一次显示表单时发生了什么,第二次没有发生?
2个回答

7

由于您描述的问题发生在JOptionPane中,这听起来像是类加载速度慢。您有没有通过网络加载?也可能是垃圾回收,因为旧窗口被处理以为新窗口腾出空间。

我会从垃圾回收开始,因为它很容易测试和纠正:在启动Java时使用-verbose:gc参数(必须从控制台执行),并注意是否在这些暂停期间运行GC。如果是,则使用-Xmx增加内存分配,并根据here所述调整堆部分。

如果是慢速网络连接的情况(像strace这样的工具可以帮助诊断),那么您需要预加载类(而不是实例化它们)。您可以使用Class.forName()在后台线程上执行此操作。

除了这两个明显的问题,您需要运行分析器以了解发生了什么。


是的,你关于垃圾回收的说法是正确的。我将最小堆大小设置为100 MB,速度(主观上)大大提高了。 - Daniel Rikowski

4
请参阅此文章获取一些性能提示。基本上,您希望尽量减少在UI线程中执行的工作,因为这会影响组件的渲染,并使其感觉很慢。
Swing应用程序有三种类型的线程: - 初始线程 - UI事件调度线程(EDT) - 工作线程
每个应用程序必须有一个代表其起点的主方法。此方法在初始或启动线程上运行。初始线程可能会读取程序参数并启动其他一些对象,但在许多Swing应用程序中,此线程的主要目的是启动应用程序的图形用户界面(GUI)。对于大多数事件驱动的桌面应用程序,一旦GUI启动,初始线程的工作就完成了。
Swing应用程序有一个单独的EDT用于UI。此线程绘制GUI组件、更新它们,并通过调用应用程序的事件处理程序响应用户交互。所有事件处理程序都在EDT上运行,您应该在EDT上编程地与您的UI组件及其基本数据模型进行交互。任何在EDT上运行的任务都应该快速完成,以便您的UI对用户输入做出响应。从其他线程访问您的UI组件或其事件处理程序会导致UI中的更新和绘图错误。在EDT上执行长时间运行的任务将导致您的应用程序变得无响应,因为GUI事件将在事件调度队列中积累。
根据评论进行更新,这里有一些其他要检查的事项: - 您是否正在运行病毒扫描程序?在我的工作机器上,病毒扫描程序会检查所有jar文件的内容,这会对启动时间产生巨大影响。如果可能,请尝试关闭病毒扫描程序或禁用该文件夹的病毒扫描程序。 - 您是否在启动时加载了额外的类?理想情况下,您应该加载轻量级委托,只有在首次调用时才加载实现(这在sWT中是常见做法,其中每个菜单项都与一个轻量级委托相关联,该委托在需要时实例化执行实际处理)。您可以尝试对应用程序进行分析以查看在启动时创建了什么,并相应地添加一些间接操作。

是的,所有这些都是非常好的建议,我在我的应用程序中都会虔诚地遵循它,但在这种情况下,我想做的唯一工作就是显示一个表单。我认为,除了可能会有许多线程问题之外,如果我将表单创建的某些部分放入线程中,我不会获得任何东西。 - Daniel Rikowski
精彩的注释,用于病毒扫描检查 JAR 文件! - shareef

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接