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

4
在我们的 Web 应用程序中,由于类加载,某些页面的第一次加载需要额外的时间,虽然不多但是明显。有没有什么聪明的方法可以在 JVM 启动时预加载 Web 应用程序类?
更新:目前我们将大量(700 个)完整的类名存储在数据库表中。我们在启动时读取该表并执行 Class.forName()。这种方法可以正常工作,但我认为可能有更聪明的方法。我们使用分析器确定了启动时引用的 700 个类。

这个回答解决了你的问题吗?在JAR启动时预加载Java类/库? - Dave Jarvis
6个回答

2

嗯,这并不是很聪明,因为它是规范的一部分,但是您可以通过在 web.xml 中的 servlet 定义中添加 load-on-startup 元素来启动 Web 应用程序时启动您的 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文件在哪里,那么您可以使用类似于此JCP论坛帖子“列出包中的类”中的代码或该线程中的一些较晚的帖子。 从类列表中,您可以获取Class对象,这将帮助加载类,而无需实例化实例。

我们这样做。当然,这只涵盖了servlets而不涉及相关的库。 - Marcus Leon
在初始化时,Servlets不能引用相关的库吗? - Eddie
他们可以。当然,您需要确定正在加载的所有类,然后在您的servlet中引用它们。我们正在寻找更简洁的方法。 - Marcus Leon
Java中的类只有在被引用时才会被加载。因此,我所知道的预加载类的唯一方法就是引用它。也许你可以有一个配置文件列出你想要引用的类,这样就可以进行配置了。仅仅引用类对象可能已经足够帮助了。 - Eddie
我们使用相当数量的库,每个库都有许多类。有什么简单的方法可以让JVM加载给定jar中的所有类?或者加载给定包中的所有类?我们可以在配置文件中列出每个类,但那将很麻烦。 - Marcus Leon
更新我的答案...如果你在配置文件中列出了你关心的每个JAR文件,那么你可以使用我提供的代码来找出JAR文件中的内容。 - Eddie

2
你可以尝试在单个虚拟类中编写静态初始化代码,然后在启动时加载该类。其静态初始化器将创建一些关键对象,导致其他类被加载(您可以递归执行此操作以改善代码模块化)。我敢打赌这样做会更简短、更简单(而且您不必担心DB问题)。
更好的方法可能是编写一个servlet,在启动时访问几个较慢加载的页面并丢弃结果。这会强制进行类加载。多次加载这些页面将增加即时编译的量(加快代码速度并摆脱JIT编译成本)。还有其他优点:这是一个“自检”,它会完成一次性启动任务,并且还可以在某种程度上预热各种高速缓存。

1

我能想到的唯一选择就是Class.forName()。如果有更聪明的替代方案,我肯定会很感兴趣听听。

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


正如更新中所提到的,这正是我们所做的。效果很好。我只是认为我们实现这个功能的方法可能有更好的方式。 - Marcus Leon

1

在线程内部使用Class.forName可能会加快速度。从第一页开始,先处理那些可能被访问的类。

将其放入线程中应该可以加快启动速度(它会更早地返回),并且由于您首先加载了更有可能被访问的类,希望在页面被访问时它们已经被加载。对于其他类也是同样的道理,在页面被访问之前希望它们已经被加载。

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

这并不保证在页面的第一次加载时不会变慢,但值得调查。


0

你可以使用第三方的JSP编译器,例如Jasper,在部署之前对JSP页面进行预编译。


1
实际的JSP编译不是问题。问题在于加载各种已编译的Java库和编译后的JSP文件。 - Marcus Leon
对不起,我误解了你的问题。希望你已经找到了解决方案。 - Mr. Will

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

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