Senior Java developer, one of the top stackoverflow users, fluent with Java and Java technology stacks - Spring, JPA, JavaEE. Founder and creator of http://computoser.com and http://welshare.com . Worked on Ericsson projects, Bulgarian e-government projects and large scale recruitment platforms. Member of the jury of the International Olympiad in Linguistics and the Program committee of the North American Computational Linguistics Olympiad. Bozhidar is a DZone MVB and is not an employee of DZone and has posted 86 posts at DZone. You can read more from them at their website. View Full User Profile

Does it Help to Move All Jars to a Shared Library?

03.08.2012
| 6498 views |
  • submit to reddit

We will be running more than one web application on the same tomcat (7.0.22), so we wondered whether there will be a benefit in moving all jars to tomcat/lib instead of having them in each application’s WEB-INF/lib (since our applications have almost identical dependencies). What this gives as benefit for sure, without even testing, is that the classes are loaded by the parent classloader, and are loaded only once, rather than by each app’s classloader.

Here are the results on my machine, with 2 applications:

Startup times (4 runs):

WEB-INF/lib

INFO: Server startup in 77554 ms
INFO: Server startup in 62391 ms
INFO: Server startup in 62598 ms
INFO: Server startup in 61002 ms

tomcat/lib

INFO: Server startup in 72321 ms
INFO: Server startup in 71151 ms
INFO: Server startup in 69841 ms
INFO: Server startup in 71047 ms

 

Memory (2 runs):

WEB-INF/lib
PermGen: size=278, Used=198
Heap: size=1,029, Used=465

PermGen: Size=276, Used=198
Heap: Size=1,049, USed=501

tomcat/lib
PermGen: Size=199, Used=151
Heap: size=1,043, Used=412

PermGen: Size=195, Used=151
Heap: size=1,035, Used=418

The only difference is in the used PermGen size, which differs with ~50 MB per app (size differs with ~80). (Used Heap goes up and down, hence the difference). This is without working wit the app, which would add a bit more difference, but most of our classes are loaded eagerly by the spring context. So this is not enough benefit for the deployment complications it introduces – you can no longer package your application directly from maven/ant – you have to post-process it to clear the jars, and also make sure your environments have up-to-date tomcat/lib folders.

 

From http://techblog.bozho.net/?p=816

Published at DZone with permission of Bozhidar Bozhanov, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Nicolas Frankel replied on Thu, 2012/03/08 - 2:19am

"Help" should be more precise in your article's title: IMHO, the shared library strategy shouldn't be approached only from a memory point-of-view. Shared libraries also let us enforce enterprise (or projects) policies like set version(s) for libraries. It also put the responsibility from the developer to the server admin for providing the right libraries in the right version.

In the last case, I was once confronted with a library that had been modified by a previous developer so that the JAR contained many more classes and was only vaguely related to its name :-/

While I agree moving libraries from each deployed package to the server reduces agility, technologies such as OSGI can help us reduce the consequences while still bringing the aforementioned benefit.

André Pankraz replied on Thu, 2012/03/08 - 3:08am

Another interesting point is project size - it's not an issue for smaller projects with few libs.

I have seen projects that have an 80 MB EAR deployment artefact - yes thats on an app server. Maybe with tomcat they would have 100 MB because of spring ;)

 

It was not easy to handle this. The build times where only one aspect, the runtime redeployment time skyrocketed.  Shared libs help a lot in this cases (and better library decissions)

 

best regards,

André

Jason Kilgrow replied on Thu, 2012/03/08 - 8:33am

It really isn't an issue of performance but one of architecture. The shared library concept is used to extend a servers runtime environment. So, if you have several apps that can take advantage of the same extended runtime environment, then the shared libraries are a good way to go because your deployments become smaller and you have less to worry about in that regard. However, the drawback is that you have more to manage on the server. That's okay if your runtime environment doesn't change often. Another benefit of using shared libraries is that you can make a change once in the shared library and all apps that run on the environment automatically get the change rather than change the library and repackage and redeploy all of your apps.

 

So it really is an architectural decision. 

Ronald Miura replied on Thu, 2012/03/08 - 2:23pm

This is a performance issue, and a deployment issue, and a security issue, and an architecture issue (well, I guess issues that cut across many aspects of the application may be considered architecture issues anyway).

Are apps big in size a problem to build and deploy? Yes.

Identical objects (in this case, classes) loaded in memory waste more memory, so it may affect performance? Yes.

Does shared libs ease locking all applications to a single lib version? Yes. (if your intention is to actually manage versioning, instead of prohibiting it, No.)

But more issues come to mind: If you share jars, you raise the risk of unintendedly sharing information between apps, which may cause security/safety problems, besides causing really hard-to-find bugs.

Seam (at least a version of it) uses a static variable to hold the application ServletContext. A colleague of mine was having problems with it, because the Seam jars were being shared between applications (JBoss), and both tried to assign its own ServletContext to it. And really crazy things may happen when you share mutable objects. It wouldn't happen if each app had its own Seam jars (static variables are scoped to the classloader).

Certainly, there are legitimate reasons to want to share information between applications, but this should be a conscious decision, not a unintended side-effect of a hack.

Personally, I think the 'agility', 'security' and 'safety' aspects are far more important than the inconvenience of dealing with big WAR files, and I'm completely against this 'enterprised-approved lib versions' approach. In terms of performance, what may cause problems are too much objects instantiated, not the classes loaded, and sharing jars doesn't help with that.

Tim Garrett replied on Thu, 2012/03/08 - 5:38pm

@Ronald +1 -- I have seen the distinction between a classloader-wide singleton and a JVM-wide singleton result in a lot of confusion.  The expectations of a framework developer should definitely be considered.  Simply moving things up in the classloader hierarchy can wreak havoc.

@Bozhidar - I agree that it is not worth the tradeoff for 50MB of memory.  Furthermore, I don't think it would ever be worth the tradeoff if you weren't developing the same way you were shipping to production.  If a choice is made to deploy JARs in production to the appserver lib directory, that same practice should be followed in development.  Maven plugins or an Ant task should make either scenario very simple.  For example, in Maven, just create a tomcat.home property in your ~/.m2/settings.xml and use a plugin like copy-dependencies.  It's been a while since I needed functionality like that, but it worked quite well at the time.  Also, in the spirit of reproducing production, if the production server has other apps not created by your team that might use some of the same libraries, I wouldn't even try to slim down the deployment in this way.

Everyone who brought up architecture is right.  This isn't something you could just safely switch in production to save RAM.  Any sysadmin who tried to mess with the deployment artifacts my team gave to QA would get an earful.

Eric Jablow replied on Sun, 2012/03/11 - 6:18pm

I know that Apache Struts, up to version 1.2.x at least, warned not to do this.

Dapeng Liu replied on Sun, 2012/03/11 - 10:40pm

centralized design always sounds bad to me 

especially if you are debugging some issues that are several versions behind, you also need to reconfig your server to have the libs that are using for that particular version 

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.