Does Tomcat load the same library file into memory twice if they are in two web apps?
I have two applications under tomcat/webapps
folder.
tomcat/webapps/App1
tomcat/webapps/App2
Both applications share the same libraries. Which are stored for example in tomcat/webapps/App1/WEB-INF/lib
.
Are both libraries loaded twice in memory?
Should I put these shared libraries in tomcat/server/lib
?
Solution 1:
As you can see here, Tomcat creates one class-loader per webapp on your server. Thus, if you have webapp1 and webapp2 that share the same library, then this library will be indeed loaded twice.
You can eventually place this library in the common directory (tomcat-dir/common/lib) if it is shared by all webapps that run on your Tomcat server.
Solution 2:
I wouldn't recommend placing the jar files in the shared folder. Let's say for example that you need in the future to deploy a third party application, that has a newer version of a jar file in the WEB-INF folder. For this application the classes of the jar will be loaded twice (even if they have the same names), one from the shared folder and one from the web app folder. This situation may cause bugs very difficult to find.
If the jar files are in the web app folders, then they are loaded by separate class loaders and don't interfere with each other.
Solution 3:
From experience: the two web-apps are entirely isolated from one another - the libraries for one are not utilised in another - thus to answer your initial question - yes they would be loaded twice.
To answer you second question, whether you should deploy these libraries into Tomcat's shared directory - I would say no, and here's why:
If you deploy a library Jar into the shared location (tomcat/server/lib), then that version of the library becomes the default for all web-applications running under that instance of Tomcat. As you can see from this overview of the tomcat architecture, the class-loader works "down the chain", with an individual web-app's lib folder being the last place it will look before it throws a class-not-found exception. This is not true in Tomcat 6 and Tomcat 7: any classes in the web apps lib and classes folder will be resolved before those in common, and thus, this will not break other apps which deploy all of their jars in the war 2.
The problem therefore of deploying a shared library to that directory is that it breaks the architecture for individual applications being isolated from one-another. Fine in your initial example, but if you want to deploy a third-party application (e.g. if you a running an app that consumes Portlet's to handle specific content), you instantly run in to version dependency issues - your shared version of a library may not be correct for the third-party application, but because the package is already loaded, you'll throw exceptions left right and centre.