ObjectInputStream.resolveClass is supposed to walk up the execution stack and
try to find the indicated class using the first class loader found (or in
CLASSPATH if none were found...). If the class cannot be found at that
location, it is supposed to throw a ClassNotFoundException, a checked exception
that it declares in its "throws" clause.
In the current build of JDK 1.2 (and for some time now, apparently), it instead
throws a NoClassDefFoundError, an unchecked exception. This wreaks havoc with
code that is expecting to catch ClassNotFoundException if the class can't be
found that way and proceed with other normal alternatives. In particular, RMI's
MarshalInputStream.resolveClass calls super.resolveClass first, and then it
catches ClassNotFoundException and tries to load the class from the annotated
codebase URL, if present. The NoClassDefFoundError prevents this fallback and
thus RMI's class loading is significantly broken.
This bug originates from the fact that the VM function FindClassFromClass() was
changed some time ago to actually post a NoClassDefFoundError on
failure instead of just returning NULL. JVM_LoadClass0(), the native function
that implements the meat of ObjectInputStream.resolveClass, was not prepared for
this change; it still just checks the return value from FindClassFromClass()
and if it is NULL, it tries to throw a ClassNotFoundException, but this is now
silently ignored because there is already the NoClassDefFoundError pending.
I'm not sure why the behavior of FindClassFromClass() was changed.
Unfortunately, the effect was not noticed earlier.