Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can multiple JVM processes share memory for common classes?

I'd like to run multiple Java processes on my web server, one for each web app. I'm using a web framework (Play) that has a lot of supporting classes and jar files, and the Java processes use a lot of memory. One Play process shows about 225MB of "resident private" memory. (I'm testing this on Mac OS X, with Java 1.7.0_05.) The app-specific code might only be a few MB. I know that typical Java web apps are jars added to one server process (Tomcat, etc), but it appears the standard way to run Play is as a standalone app/process. If these were C programs, most of that 200MB would be shared library and not duplicated in each app. Is there a way to make this happen in Java? I see some pages about class data sharing, but that appears to apply only to the core runtime classes.

like image 371
Rob N Avatar asked Nov 21 '12 15:11

Rob N


4 Answers

At this time and with the Oracle VM, this isn't possible.

But I agree, it would be a nice feature, especially since Java has all the information it needs to do that automatically.

Of the top of my hat, I think that the JIT is the only reason why this can't work: The JIT takes runtime behavior into account. So if app A uses some code in a different pattern than app B, that would result in different assembler code generated at runtime.

But then, the usual "pattern" is "how often is this code used." So if app A called some method very often and B didn't, they could still share the code because A has already paid the price for optimizing/compiling it.

What you can try is deploy several applications as WAR files into a single VM. But from my experience, that often causes problems with code that doesn't correctly clean up thread locals or shutdown hooks.

like image 162
Aaron Digulla Avatar answered Sep 19 '22 01:09

Aaron Digulla


IBM JDK has a jvm parameter to achieve this. Check out @ http://www.ibm.com/developerworks/library/j-sharedclasses/

And this takes it to the next step : http://www.ibm.com/developerworks/library/j-multitenant-java/index.html

like image 21
user170008 Avatar answered Sep 19 '22 01:09

user170008


If you're using a servlet container with virtual hosts support (I believe Tomcat does it) you would be able to use the play2-war-plugin. From Play 2.1 the requirement of always being the root app is going to be lifted so you will probably be able to use any servlet container.

One thing to keep in mind if that you will probably have to tweak the war file to move stuff from WEB-INF/lib to your servlet container's lib directory to avoid loading all the classes again and this could affect your app if it uses singleton or other forms of class shared data.

like image 36
Maurício Linhares Avatar answered Sep 21 '22 01:09

Maurício Linhares


The problem of sharing memory between JVM instances is more pressing on mobile platforms, and as far as I know Android has a pretty clever solution for that in Zygote: the VM is initialized and then when running the app it is fork()ed. Linux uses copy-on-write on the RAM pages, so most of the data won't be duplicated.

Porting this solution might be possible, if you're running on Linux and want to try using Dalvik as your VM (I saw claims that there is a working port of tomcat on Dalvik). I would expect this to be a huge amount of work, eventually saving you few $s on memory upgrades.

like image 38
onon15 Avatar answered Sep 22 '22 01:09

onon15