如何在启动时在JVM中预加载Web应用程序类?

时间:2009-03-19 21:30:50

标签: java performance web-applications jvm classloader

在我们的网络应用程序中,由于类加载,一些页面的第一次加载需要一些小但明显的时间。有没有人有任何聪明的方法在启动时在JVM中预加载Web应用程序类?


更新:我们现在所做的是在db表中存储一堆完整的类名(700)。我们在启动时读取表并执行Class.forName()。它工作正常,但我认为可能有一个更聪明的方法。我们通过使用分析器确定了在启动时引用的700个类。

6 个答案:

答案 0 :(得分:2)

嗯,它不是很聪明,因为它是规范的一部分,但是你可以在启动Web App时通过将load-on-startup元素添加到web.xml中的servlet定义来启动servlet:

<servlet>
  <description>....</description>
  <display-name>....</display-name>
  <servlet-name>....</servlet-name>
  <servlet-class>....t</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

如果您为一组有代表性的服务执行此操作 - 或者只是一个可以预加载所需内容的servlet - 那么您将实现目标。

如果这还不够,如果你想从JAR文件加载类,例如,没有以有意义的方式实际初始化它们,并且你知道你的JAR文件在哪里或者可以找出你的JAR文件在哪里,然后你可以使用this JCP forum post "List classes in package"中的代码或该线程中的一些后期帖子。从类列表中,您可以获取Class对象,这将有助于加载类而无需实际实例化实例。

答案 1 :(得分:2)

您可以尝试在单个虚拟类中编写静态初始化程序代码,然后在启动时加载该类。它的静态初始化程序会创建一些导致其他类加载的关键对象(并且可以递归地执行此操作以提高代码模块性)。我敢打赌,这个更简单,更简单(并且您无需担心数据库问题)。

更好的方法可能是编写一个servlet,它在启动时会触及一些缓慢加载的页面并丢弃结果。这会强制类加载。每次加载这些页面多次次都会增加实时编译的数量(加快代码加速并使JIT编译成本不受影响)。还有其他优点:这是一个“开机自检”,它会导致一次性启动任务完成,并且它还可能会使各种缓存达到某种显着程度。

答案 2 :(得分:1)

Class.forName()是我唯一能想到的。我当然有兴趣听到更聪明的选择。

另一种选择是选择一组URL并在启动时运行脚本以点击这些URL。

答案 3 :(得分:1)

线程内部的Class.forName可能会加快速度。从可能被击中的第一页上的那些开始。

线程化它应该使启动更快(它将更早返回)并且因为你开始加载更可能的类首先它们将有希望在页面被命中时被加载。对于其他同样的交易,希望在页面被点击之前加载。

您还可以进一步采取并为每组类启动一个线程(给定页面上所需的那些类将是一个组)。这可能会加快速度,因为您可以并行化从磁盘读取(但这也可能会减慢速度)。

这并不意味着在第一次加载页面时事情不会变慢,但值得研究。

答案 4 :(得分:0)

您可以使用第三方jsp编译器(例如Jasper)在部署JSP页面之前对其进行预编译。

答案 5 :(得分:0)

可能你可以尝试将700个类转换为jar文件并应用一些预加载方法,可能是将jar放在引导类路径中(我不确定它是否有效..但只是提示)。 / p>