13
votes

I know that a servlet container, such as Apache Tomcat, runs in a single instance of the JVM, which means all of its servlets will run in the same process.

I also know that the architecture of the servlet container means each web application exists in its own context, which suggests it is isolated from other web applications.

As depicted here: alt text

Accepting that each web application is isolated, I would expect that you could create 2 copies of an identical web application, change the names and context paths of each (as well as any other relevant configuration), and run them in parallel without one affecting the other. The answers to this question appear to support this view.

However, a colleague disagrees based on their experience of attempting just that.

They took a web application and tried to run 2 separate instances (with different names etc) in the same servlet container and experienced issues with the 2 instances conflicting (I'm unable to elaborate more as I wasn't involved in that work).

Based on this, they argue that since the web applications run in the same process space, they can't be isolated and things such as class attributes would end up being inadvertently shared. This answer appears to suggest the same thing

The two views don't seem to be compatible, so I ask you: Do servlet containers prevent web applications deployed to the same container from conflicting with each other?

If yes, How do they do this?

If no, Why does interference occur?

and finally, Under what circumstances could separate web applications conflict and cause each other interference?, perhaps scenarios involving resources on the file system, native code, or database connections?

3

3 Answers

16
votes

The short answer is that the servlet container isolates the applications by using a separate classloader for each application - classes loaded by separate classloaders (even when from the same physical class files) are distinct from each other. However, classloaders share a common parent classloader and the container may provide a number of other container-wide resources, so the applications are not completely isolated from each other.

For example, if two applications share some common code by each including the same jar in their war, then each application will load their own instance of the classes from the jar and a static variable (e.g. a singleton) of a class in one application will be distinct from the static variable of the same class in the other application.

Now, take for example, that the applications try to use java.util.Logger (and presumably don't include their own instance of the Logger classes in their war files). Each application's own classloader will not find the class in the war file, so they will defer to their parent classloader, which is probably the shared, container-wide classloader. The parent classloader will load the Logger class and both applications will then be sharing the same Logger class.

6
votes

Servlets in the same container will share some resources. I think it should be possible to deploy the same web application twice in the same container provided that you give each a different name and they don't collide on a particular resource. This would theoretically be the same as deploying two different servlets which just happen to have the same implementation, which we do all the time.

Some shared resources, off the top of my head (and I'm not an expert so don't quote any of this!):

  • Libraries (jars) in tomcat/common/lib (Tomcat 5) or tomcat/lib (Tomcat 6).
  • Settings in the global server.xml, web.xml, tomcat-users.xml
  • OS provided things, such as stdin/stdout/stderr, network sockets, devices, files, etc.
  • The logging system.
  • Java system properties (System.getProperty(), System.setProperty())
  • I suspect... static variables? I'm not sure if the ClassLoader design would prevent this or not.
  • Memory. This is the most common problem: one servlet can deny others availability by consuming all memory.
  • CPU - especially with multi-threaded apps. On the HotSpot JVM, each Java thread is actually an OS-level thread, which are expensive and you don't want more than a few thousand of them.

Doubtless there are more.

Many of these things are protected by a security manager, if you're using one.

2
votes

I believe the isolation is in the class loader. Even if two applications use the same class name and package, their class loader will load the one deployed with the application.