Thursday, June 17, 2010

Eek! Java reflection can cause NoClassDefFoundError after 15 calls

Now this came as a bit of a surprise to me. Reading this thread on the Felix mailing list...

I can't believe this: when using reflection after about 15 calls, the internal behaviour of the Sun JRE changes. With the changed behaviour comes in a package dependency on the sun.reflect package! When running under OSGi you are very much in charge of what comes in via the classloader so a new package that comes in over the same code path after about 15 calls is bad news - you really want to know your package dependencies up front.
The solution is obviously to import that sun.reflect package in your affected bundle but how are you supposed to know? Let's say you have a test suite that properly tests your code and everything is looking nice. I would imagine that a testsuite doesn't test every method call 15 times to make sure its still ok. Moreover, how do we know it's 15? There could be another optimization lurking in the JRE that requires 300 calls in order for it to be exposed.
Another problem with importing sun.reflect is that it's implementation specific. Do other implementations have a similar issue?

Here's a message to all JVM implementors: optimize all you can but please don't change the package dependency graph after a number of invocations. At the very least make your implementation fail fast, not after x method calls.

There is a bug for this at sun: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6265952
Accepted in 2005 but still open...

2 comments:

Tim Diekmann said...

This is scary stuff.

Issues like these make it even harder to convince people that OSGi is the right thing to use for your modularization needs.

Val Urbansky said...

Actually why do not optimize the graph of dependencies? Is it stated somewhere in JLS?

JMO, it is rather bad idea to load only public API by system classloader.