Skip navigation.

Notes to self

Whatever I feel like writing

Posts tagged with "jboss"

Permgen: Our Workable solution.

, , , ...

The majority of the visitors to this blog, I just noticed, come here because they are interested in my permgen saga:

  1. Good Riddance, PermGen OutOfMemoryError!
  2. PermGen Strikes Back!
  3. Return of the PermGen


The last installment concluded with newfound hope in the JDK6 profiling tools and a promise to post back as more knowledge was uncovered. Well... that was a while ago.

So, why haven't I spent time blogging about all of the exciting findings I must have made along my quest to solve this problem, since the 29th of September, 2007? The answer is simple: I have not spent any time at all on this problem. The reason for this lack of effort is simple: permgens have not been a problem to me since about that time.

To properly explain what has happened, let me draw a parallel to writing code - multi-threaded code, to be presice: What is the primary concern in multi-threaded/concurrent code? Shared mutable state. The easiest way to solve this problem? Do not share state, or make shared state immutable.

Neither of these proposed solutions actually solve the problem of shared mutable state. Instead they remove it; make the problem moot - a non-issue.

I have not solved the permgen problem; I have made it moot. Well, the operations department have made it moot and I have been cheering from the side-line.

The Moot Permgen:

Recall the original problem: every so often we redeploy a Java web application on our application servers, without restarting said servers. An intricate object graph prevents the old class files from being unloaded, this equates to a memory leak in the permanent generation of the JVM that eventually causes the server to die with an OutOfMemoryError.

The thing that gets the hair ball rolling here, is the deployment without restarting the server. To make this problem moot, all we have to do is to always restart the server every time we deploy an application.

Simple, right?

It's like when you go to the doctor and say "It hurts when I do this" and the doctor says "Well, don't do that." Same exact thing. Deployment without a restart: Just stop it!

The Other Way around the problem:

We basically changed the way we deploy applications. Not in a big way, just some small adjustments.

First and foremost, we don't deploy anything without restarting the server - but you already knew that.

Second, we deploy less stuff on our servers - the fewer apps you run on a server, the faster it'll restart. Preferably, we would only run one application per JVM- this way, the restartes would only affect a single application.

Lastly, we're moving our production systems to load-balanced setups. When an application is running on two (or more) servers behind a load-balancer, then restarting a server won't incur any down-time.

It's not rocket science. It's a practical and workable way to simply avoid having to deal with the dreaded OutOfMemoryError: permgen.

Good Riddance, PermGen OutOfMemoryError !

, , , ...

Hi, you're probably here because you are hot-deploying some Java web applications and you have problems with some PermGen: OutOfMemoryErrors. Then you somehow found a link to an article that claimed to solve this very problem.

Well, that article was wrong. So I put up a big red note, but people still link to it.

So, in an attempt to set things straight again, I present a short list of facts that I have collected since I wrote the original article:

  • Bugs in the Sun garbage collector is one source of this problem.
  • There are (were? can't be arsed to check) more than one bug, hence confusion.
  • Your app failing to undeploy completely will leak all classes in your app, every time you redeploy - this is another source of the problem.
  • None of these sources can be fixed with GC flags.
  • The JRocket JVM does NOT fix this problem - it simply lets the permgen grow unbounded, until something bad happens, like swap-thrashing or the OS kills it.

The only solution I have found that is feasible, reliable and portable is this: reboot your servers!

P.S. Don't bother giving me links to other articles on this issue. Even if you happen to find something I haven't already read, chances are that it is simply rehashing stuff I already know.

Thanks!


Bellow this line is the original article with all it's faulty conclusions.
-----------------------------------------------------------------------------------------------------------------------
I did it!

Yes, lads & lasses! If you've been annoyed with having JBoss or Tomcat die with an OutOfMemoryError every fifth time you redeploy your beloved brainchild of a web application, then this is your lucky day! Because I found a fix! It's true! Yay! ....!!!!!11one (can you tell this has been a pain to me?)

Boring but Serious Theory and Hypothesis part:
The "PermGen" error happens, when the Java virtual machine runs out of memory in the permanent generation. Recall that Java has a generational garbage collector, with four generations: eden, young, old and permanent.

In the eden generation, objects are very short lived and garbage collection is swift and often.

The young generation consists of objects that survived the eden generation (or was pushed down to young because the eden generation was full at the time of allocation), garbage collection in the young generation is less frequent but still happens at quite regular intervals (provided that your application actually does something and allocates objects every now and then).

The old generation, well, you figured it. It contains objects that survived the young generation, or have been pushed down, and garbage collection is even less infrequent but can still happen.

And finally, the permanent generation. This is for objects that the virtual machine has decided to endorse with eternal life - which is precicely the core of the problem. Objects in the permanent generation are never garbage collected; that is, under normal circumstances when the jvm is started with normal command line parameters.

So what happens when you redeploy your web application is, that your WAR file is unpacked and its class files loaded into the jvm. And here's the thing: almost always ends up in the permanent generation... Because, seriously, who wants to garbage collect their classes?!? Well, apparently application servers do, and here's how we make that happen;

PermGen, The Fix:
The standard garbage collector can't collect in the permanent generation, but the concurrent collector can. So the first thing we need to do is to make sure that the jvm uses the concurrent garbage collector. This is done by putting this:

> -XX:+UseConcMarkSweepGC

In java's command line arguments. But this is not enough. We must also specifically tell it to collect in the permanent generation, and this is done with this command line argument:

> -XX:+CMSPermGenSweepingEnabled

Good, now the concurrent collector will take the permantent generation under its wings. But wait! Classes are special, and the jvm is reluctant to let go of them, so we must also explicitly allow classes to be unloaded:

> -XX:+CMSClassUnloadingEnabled

Now we're certain that the permanent generation will be properly cleaned. But this raises another issue: what if the jvm unloads classes that might still be needed? I imagine it can be hard for a collector to tell whether or not a class might still be needed with the amount of reflection that goes on in an application server. Therefor, we might want to tweak the amount of memory allocated for the permanent generation, and this is done with this command line parameter:

> -XX:MaxPermSize=128m

Which will set the maximum size of our permanent generation to 128 megabytes - tweak it to fit your needs.

With these parameters properly applied to the jvm that runs your application server, your chances of running into a PermGen OutOfMemoryError will be considerably lessened.

Take care!