【问题标题】:How can I preload web app classes in the JVM on start up?如何在启动时在 JVM 中预加载 Web 应用程序类?
【发布时间】:2009-05-22 05:08:52
【问题描述】:

在我们的 Web 应用程序中,由于类加载,某些页面的首次加载需要花费少量但值得注意的额外时间。有没有人有任何聪明的方法在启动时在 JVM 中预加载 Web 应用程序类?


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

【问题讨论】:

标签: java performance web-applications jvm classloader


【解决方案1】:

好吧,它不是很聪明,因为它是规范的一部分,但是您可以通过在 web.xml 中的 servlet 定义中添加 load-on-startup 元素来让您的 servlet 在 Web 应用程序启动时启动:

<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 对象,这将有助于加载类,而无需实际实例化实例。

【讨论】:

  • 我们这样做。这当然只涵盖 servlet 而不是相关的库。
  • servlet 不能在初始化时引用相关的库吗?
  • 他们可以。您当然需要确定所有正在加载的类,然后在您的 servlet 中引用它们。我们正在寻找更清洁的方法。
  • Java 中的类仅在引用时才加载。因此,我知道预加载类的唯一方法是引用它。也许你可以有一个配置文件列出你想要引用的类,所以它是可配置的。仅引用 Class 对象可能就足够了。
  • 我们使用了大量的库,每个库都有很多类。让 JVM 只加载给定 jar 中的所有类的简单方法是什么?或者加载给定包中的所有类?我们可以在配置文件中列出每个类,但这会很麻烦。
【解决方案2】:

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

更好的方法可能是编写一个 servlet,它在启动时会遇到一些加载缓慢的页面并丢弃结果。这会强制加载类。每次加载这些页面多次 次都会增加完成的即时编译量(既可以加快您的代码速度,又可以减少 JIT 编译成本)。还有其他好处:这是一种“开机自检”,它会导致一次性启动任务完成,并且它还可以在一定程度上启动各种缓存。

【讨论】:

    【解决方案3】:

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

    另一种选择是选择一组 URL 并在启动时运行脚本来访问这些 URL。

    【讨论】:

    • 正如更新中提到的,这正是我们所做的。效果很好。我只是认为会有比我们实施此方法更好的方法。
    【解决方案4】:

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

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

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

    这并不能保证在第一次加载页面时速度不会变慢,但值得研究。

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 实际的 JSP 编译不是问题。它正在加载各种已编译的 Java 库和已编译的 JSP 文件。
      • 对不起。我误解了你在问什么。希望您找到解决问题的方法。
      【解决方案6】:

      也许您可以尝试将 700 个类转换为 jar 文件并应用一些方法进行预加载,可能通过将 jar 放在引导类路径中(我不确定它是否有效..但只是给出提示)。

      【讨论】:

        猜你喜欢
        • 2021-02-08
        • 2018-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多