views:

801

answers:

6

In our web apps the first load of some pages takes a small but noticeable extra about of time due to class loading. Does anyone have any clever ways of preloading web app classes in the JVM on start up?


Update: What we do now is store a bunch (700) of full class names in a db table. We read the table at startup and do Class.forName(). It works fine but I thought there might be a more clever approach. We determined the 700 classes that were referenced at startup by using a profiler.

+1  A: 

Class.forName() is about the only thing I can think of. I'd certainly be interested in hearing more clever alternatives.

Another option would be to select a set of URLs and run a script on startup to hit those URLs.

Travis Jensen
As mentioned in the update this is exactly what we do. Works well. I just thought there would be a better approach than how we have implemented this.
Marcus
A: 

You could always use a third party jsp compiler, such as Jasper, to precompile your JSP pages before you deploy them.

Mr. Will
The actual JSP compiling isn't an issue. It's loading the various compiled Java libraries and compiled JSP files.
Marcus
I'm sorry. I misunderstood what you were asking. I hope you found a solution to your problem.
Mr. Will
+2  A: 

Well, it's not very clever as it's part of the specification, but you can have your servlets be started when the Web App is started by adding the load-on-startup element to the servlet definition in web.xml:

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

If you do this for a representative set of services -- or perhaps just one servlet that can preload everything needed -- then you'll achieve your goal.

If this isn't sufficient, if you want to load classes from JAR files, for example, without actually initializing them in a meaningful way, and if you know where your JAR files are or can figure out where your JAR files are, then you can use something like the code at this JCP forum post "List classes in package" or some of the later posts in that thread. From the list of classes, you can get the Class objects, which will help load the classes without actually having to instantiate an instance.

Eddie
We do this. This of course just covers the servlets and not the associated libraries.
Marcus
Can't the servlets, in their initialization, reference the associated libraries?
Eddie
They can. You would of course need to determine all the classes that are being loaded and then reference them all in your servlet. We were looking for a little more cleaner approach.
Marcus
Classes in Java are loaded only when referenced. Thus, the only way I am aware of to pre-load a class is to reference it. Perhaps you could have a configuration file that lists classes you want to reference, so it's configurable. Just referencing the Class objects may be enough to help.
Eddie
We use a fair number of libraries each of which have many classes. What would an easy way to get the JVM to just load all the classes in a given jar? Or to load all the classes within a given package? We could list every single class in a config file but that would be cumbersome.
Marcus
Update my answer ... If you list every JAR file you care about in a configuration file, then you can use code I linked to to figure out what's in the JAR file.
Eddie
+1  A: 

The Class.forName inside of a thread would potentially speed things up. Start with the ones that are on the first page likely to be hit.

Threading it should make the startup quicker (it'll return earlier) and since you start loading the more likely classes first they will hopefully be loaded by the time the page gets hit. For the others same deal, hopefully loaded before the page gets hit.

You could also take it further and start a thread for each group of classes (those classes needed on a given page would be a group). Which might speed things up since you could parallelize the reading from disk (but that might also slow it down).

This doesn't grantee that things won't slow down on the first load of a page, but it is worth investigating.

TofuBeer
A: 

May be you can try converting the 700 classes to a jar file and apply some methods for preloading,probably by putting the jar in boot class path (I am not sure if it works ..but just giving a hint ).

AIB
+1  A: 

You might try writing static initializer code in a single dummy class and then load that class at startup. Its static initializer would create a few key objects that cause other classes to be loaded (and you could do this recursively to improve code modularity). I'd bet this is much shorter and simpler (and you have no DB issues to worry about).

A better approach probably is to write a servlet that on startup hits a few of your slow-loading pages and throws away the results. This forces class loads. Loading these pages many times each will increase the amount just-in-time compilation done (both speeding up your code and getting JIT compilation costs out of the way). There are other advantages too: this is a "power-on self-test", it causes one-time startup tasks to be done, and it may also prime various caches to some noticable degree.

Jim Ferrans