Monday, January 26, 2009

java.lang.OutOfMemoryError: PermGen space

You know those things that don't crop up very often, but when they do they're a complete pain in the a**? well this is one of them!

Developing a plugin for Atlassian Jira, I don't care about heap size, or space allocated to PermGen, all I care about is getting functionality to the business.
I've read this:
and this:
among many, enough to know that PermGen isn't as simple as "make the heap bigger", enough to know that it's probably the fact that I'm running the app server in debug mode that contributes to this problem, but still, I'd rather not have to deal with it.

I understand that there's a lot of complexity involved in the Java Memory Model, I understand that people a lot smarter than me came up with it and decided on restrictions like the fact that the JVM can't give memory back to the OS once it's freed it, to make the problem of Performant Garbage Collection solvable, I'm cool with all that!

But... I just want it to work! I wish there was a --XX:PromiscuosMemory flag that I could set to say, hey, I'm developing here, this won't be used in production, I know what I'm doing, I don't mind if I take a bit of a hit on performance, but I would like you to eat memory as needed until you reach the system limit, running the garbage collector whenever you want, and you know, if you get a whole lot to spare? Just go on and give it back to the OS, thanks.

Of course that doesn't exist, so I find myself adding "-XX:MaxPermSize=512m -Xms128m -Xmx512m" to my startup script, and not caring about the memory model anyway. fun fun.

Using Reflection to get around hard-coded dependencies

Spring famously has no cycles in it's dependency graph:
Obviously writing applications is different to writing frameworks, and we can't always take the time to get things so polished. Also by the nature of the beast the domain model will (should!) pervade the entire application (domain model should be the root of your graph, with services/repositories/ etc depending on them).

Sometimes though you may want to enable some functionality if an object is an instance of some special class, without introducing explicit dependencies on those classes. reflection is your friend!!
Of course the price is that you loose type-safety, so be warned here be dragons!!

simply at runtime see if the string representing the class name is the class you want to twiddle, if it is, reflectively invoke your methods enabling additional functionality, otherwise continue on in the boring type-safe way that only deals with the interface or bace class you're dealing with. The key here is that by default you deal with a standard interface or base class (such as javax.activation.DataSource), and only if the instance of the object has the extra bits you want (eg, then you selectively elect to do extra. Spring does this quite a lot with it's own DataSource wrappers internally.

handy sometimes...

Classloading in Application Servers: JARmaggedon!

original issue with trying to access the tomcat security principal in IMGWS, but since class was loaded from a sibling classloader, not a direct parent was unable to cast the object to the correct class to access it, even though debugging revealed it to be the correct object. Problem: class loaded from an unavailable classloader, so unable to use any methods or fields related to the class, have to break in through reflection.

current issue: upgrading JBoss 4.0.4 to JBoss 4.2.3, except that we use spring hibernate, and JBoss tries to be helpful by providing those jars as well, thanks JBoss, now I get
java.lang.ClassCastException: cannot be cast to org.hibernate.event.PostInsertEventListener

Solution? remove hibernate jars from jboss server/default/lib. this works ok in dev, but will probably break advanced jboss functionality which relies on those jars, lucky I don't use it... :-)

Our deployment scenario is amenable to not having spring/hibernate etc jars provided by app server, instead provided by each applications WAR. for us this works as we have one app per app server, but as more come online this may change. On the other hand, each application providing all it's own dependencies may cause some duplication of libraries and cost disk space, but this is a cheap price to pay for applications to evolve at their own rates and not be constrained by server dependencies, eg - I need a feature in hibernate 3.3.0, but in prod we only have 3.2.2. No thanks!
Personal opinion is that applications should be as self-contained as possible to simplify deployment and dependency management (leave that to maven). the exception to that is infrastructure explicitly provided by the app server, eg servlets, ejb3 persistence maybe, JDBC drivers definitely. Big fat WAR is Not A Problem, compared to Jarmeggadon...

Wednesday, January 14, 2009

System Antics

I've had the 3rd edition of this book in my amazon wishlist for ages, now I finally found an online version of the first edition which is short & pithy. read the preface then if you like it check out the rest. fantastic discussion of systems in general (in the sense of systems that humans set up, including but not limited to IT systems, including organisations, governments & companies etc) especially relating to failure modes.