|
|
||
Osvaldo Pinali Doederlein's BlogJune 2007 ArchivesIncredible bug in Intersystems Cache's EJB codePosted by opinali on June 28, 2007 at 06:38 AM | Permalink | Comments (9)
To make the story short: Caché (a pure OODBMS) contains a code generator that produces all code you need to EJB-ize some Java class, a process known as Projection. The evil part is the code it generates for the Entity Beans's unsetEntityContext() method. These methods contain the following code:
Now, how STUPID is that? Because of this explicit GC call, performed repeatedly by EVERY SINGLE BEAN, the JVM would freeze with 100% CPU usage for several minutes, when the application server decided to clean up its cache, removing hundreds of expired entity beans. The problem apparently happened only on a setup using JBoss 4.2.0 and Sun JDK 1.5.0_09 but not in another with JBoss 4.0.2 and Sun JDK 1.5.0_11, both with similar (JBoss's factory-standard) JVM settings. It's possible that the JDK contributed to the problem. A forced full-GC shouldn't take a lot of time in a JVM that's mostly idle except for a simple cache reaper, and with 120Mb of used heap out of 512Mb. It was taking 1 full second per GC. I guess the long GC time could have been caused by some of the several GC bugs fixed by JDK 1.5.0_10, but I didn't investigate further. I told the client to add -XX:+DisableExplicitGC to the server launching script. It's been several years now that there is NO reason to invoke System.gc() in Java VMs in normal code, only in very special cases (e.g., I do it a lot in microbenchmarks because I want to start each test cycle with the heap in a similar state). Even management/cleanup features in the core of application servers shouldn't do it (one never knows when a burst of client requests may arrive), let alone application code. Thumbs down to JBoss for not disabling explicit GC by default; and two thumbs down to the J2EE / Java EE specs for not forbidding it in app code, at least I didn't find such rule in the specs. Now, how many thumbs down for Intersystems? I'll have to unwear my shoes and I'll be missing a few thumbs still. This mistake is typical of a Java rookie (and a bad one), it's embarrassing in a product of a respected software company. Your Studio doesn't seem to offer an option to disable generation of the System.gc() calls; I don't know the product and perhaps there is a way, but this "feature" should not exist even as an optional / non-default choice. Just find whoever did this, and fire the idiot. I considered writing this blog in politically correct mode, i.e. "in a certain OODBMS's EJB support..." but I decided to be more explicit because all Caché customers should be warned about this issue, even if it's just potential issue, limited to some JVM builds only. (The JVM has no obligation to respond fast to dumb explicit GC calls, even when a boatload of free space exists; the fact that it happens most of the time, in most JVMs under common configurations, is just a bonus.) One last remark: diagnosing this bug was a piece of cake thanks to the JDK's jstat and jstack tools. The RAS facilities of the JVM often saves my day, it's a top item in my list of "why I use Java instead of X, Y or Z". | ||
|
|