2

I have a Tomcat 6 server on an Ubuntu 12.04 server with 4GB and the following JAVA_OPTS

JAVA_OPTS="-Djava.awt.headless=true -Xms512M -Xmx512M -XX:PermSize=1024M -XX:MaxPermSize=1024M -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"

Dumb question: If I deploy the same webapp (same war file) several times (each references a different Postgres database) - as server.com:8080/webapp1 server.com:8080/webapp2 etc...

may I assume that Tomcat will be caching the class files once across the multiple webapps? Or - does Tomcat cache classes per Webapp?

Thanks in advance Danny

Danny Lieberman
  • 205
  • 2
  • 7

1 Answers1

2

The answer depends on where you have located the class file(s) used by your webapp.

If you put a given class in the Tomcat Common class loader path of $CATALINA_HOME/lib it will be made available to all webapps. The same goes for its cached form.

If you use the Tomcat web application class loader path of webapps/webapp/WEB-INF/classes and webapps/webapp/WEB-INF/lib the classes and corresponding class caches are isolated between applications.

Technical background

Tomcat does not conform to the way Java natively processes classes, but uses a custom Java class loader.This is to enforce a number of features relating to:

  • class processing within a webapp
  • class caching per webapp
  • preloading and reloading of classes at webapplication startup/runtime
  • security in class loading/referencing

The Tomcat custom class loader uses the Java default Bootstrap, Extension and System class loaders, but substitutes the classpath variable used by the System class loader for its own classpath. This has the effect of:

  • replacing the Endorsed Standards Override Mechanism shipped with Java, with Tomcats own.
  • adding two additional class loaders at the end of the Java class loading hierarchy:

    • The Tomcat Common class loader
    • A separate class loader per webapp

The original classpath is ignored by Tomcat.

A key detail is that a webapp class loader does not delegate class loading to its parents first, but tries to load each class as it is requested. Each loaded class is subsequently cached by the webapp class loader in question. This classloader/cache level can not be shared between webapps.

Everything class loaded by the Common class loader is made publicly available to all webapps, including the cache. Extensive placement of classes in the Common class loader path is discouraged as it:

  • breaks portability
  • class version requirements may be different between Tomcat and different webapps.
  • maintenance becomes an issue, which class belonged to what?

There is quite a bit of fine print attached to the class loading/caching/reloading process. If that is important my suggestion would be to read the outstanding chapter on class loading in the Professional Apache Tomcat 6.

A compressed version has been written by someone on this page.

ErikE
  • 4,676
  • 1
  • 19
  • 25
  • 1
    Erik - Great answer. For a development server it makes perfect sense. For production, I am not so sure. Given a production instance of several webapps running the same code but with different databases ( a common use case for us ) it seems logical to me to put the Also - I note that if you crash on permgen out of memory in one webapp - the entire tomcat 6 instance crashes since permgen is Tomcat-wide. – Danny Lieberman Dec 08 '13 at 09:23
  • Danny, I believe most solutions have merit depending on context. If you have a grip on the facts as available to you and they point you in a given direction - why go anywhere else? I would guess the discouraging part from those with deep Java/Tomcat insight is more about raising awareness than setting a rule in stone. – ErikE Dec 09 '13 at 20:34