If you tried using these counters for yourself, you may have noticed that any time you recompiled one, its count automatically began again at 1. Trust us--it's not a bug, it's a feature. Most servers automatically reload a servlet after its class file (under the default servlet directory, such as server_root/servlets) changes. It's an on-the-fly upgrade procedure that greatly speeds up the development-test cycle--and allows for long server uptimes.
Servlet reloading may appear to be a simple feature, but it's actually quite a trick--and requires quite a hack. ClassLoader objects are designed to load a class just once. To get around this limitation and load servlets again and again, servers use custom class loaders that load servlets from the default servlets directory. This explains why the servlet classes are found in server_root/servlets, even though that directory doesn't appear in the server's classpath.
When a server dispatches a request to a servlet, it first checks if the servlet's class file has changed on disk. If it has changed, the server abandons the class loader used to load the old version and creates a new instance of the custom class loader to load the new version. Old servlet versions can stay in memory indefinitely (and, in fact, other classes can still hold references to the old servlet instances, causing odd side effects, as explained in Chapter 11, "Interservlet Communication"), but the old versions are not used to handle any more requests.
Servlet reloading is not performed for classes found in the server's classpath (such as server_root/classes) because those classes are loaded by the core, primordial class loader. These classes are loaded once and retained in memory even when their class files change.
It's generally best to put servlet support classes (such as the utility classes in com.oreilly.servlet) somewhere in the server's classpath (such as server_root/classes) where they don't get reloaded. The reason is that support classes are not nicely reloaded like servlets. A support class, placed in the default servlets directory and accessed by a servlet, is loaded by the same class loader instance that loaded the servlet. It doesn't get its own class loader instance. Consequently, if the support class is recompiled but the servlet referring to it isn't, nothing happens. The server checks only the timestamp on servlet class files.[3]
[3] For the daredevils out there, here's a stunt you can try to force a support class reload. Put the support class in the servlet directory. Then convince the server it needs to reload the servlet that uses the support class (recompile it or use the Unix utility touch). The class loader that reloads the servlet should also load the new version of the support class.
A frequently used trick to improve performance is to place servlets in the default servlet directory during development and move them to the server's classpath for deployment. Having them out of the default directory eliminates the needless timestamp comparison for each request.
Copyright © 2001 O'Reilly & Associates. All rights reserved.