users@glassfish.java.net

Re: Glassfish Memory Issues

From: <glassfish_at_javadesktop.org>
Date: Thu, 12 Jul 2007 13:41:09 PDT

Just to be clear about what Scott is talking about here.

What happens pre-1.6 (and note, simply changing the JDK won't fix it, I believe you need to install a JAR file as well, at least for SJAS 9.0/GF v1, maybe not for GFv2 beta), is that when you need to compile a JSP, the JVM runs an external process to perforn the compile. Specifically, perhaps among others, it runs "javac".

Now, the way UNIX does this is that it forks the running process, and then the new fork executes an exec call that replaces the current process with the new one.

Forking the process makes a perfect copy. Simply, the process stops for an instant, the OS makes a copy, then both processes start right back up at the same point as where the fork happens, but the parent process gets a valid process id as a result of the fork call, while the child gets a 0. The child process sees that it got the 0, and then calls exec. Exec replaces the running process with a new one.

But the key is that for the split second that child process is looking at the 0 result, and building up the exec call, it's a literal duplicate of the parent process.

So, if you have a 512MB process running, and you then run fork and exec, even if you are execing a 1K process, for a short time you will have 2 512MB processes.

Now, in truth the system goes through some shenanigans to reduce the impact of a fork. For example, it doesn't literally copy all 512MB of the parent process. But what it does do is it has to go through much of the preparation AS IF IT WERE going to copy all 512MB of the parent process. The OS doesn't know what you're going to do, so it has to assume that you will use all of it, even if it you're not going to.

So, that's where the Swap area comes in to play. What the system does is rather than making a physical copy of the process image, it blocks out chunks of the swap area and dedicates them to your new process. That way, if and when you actually use the memory in your new process, there's a place for it. (This is all pretty high level, Virtual Memory systems are far from trivial, but the gist is the same).

So, for that short moment in time, you need to have free space in the swap file for your new process. If you have a low amount of swap, then that reservation of space will fail.

Java 1.6 fixes that problem by letting Glassfish use an java compiler internal to its JVM, rather than having to fork a process to perform the compile. Now the overhead is simply whatever is needed by the compiler and the files it is compiling, in space that will soon be GC'd, rather than needing an entire transient copy of the process. This is what makes it overall faster and much more memory efficient.

Basically search for Glassfish, java 1.6, and JSP compile and you'll hunt down the details of setting this up -- it's not simply changing the JVM.
[Message sent by forum member 'whartung' (whartung)]

http://forums.java.net/jive/thread.jspa?messageID=226455