Java Reference
In-Depth Information
Both Strange1 and Strange2 use this class:
class Missing {
Missing() { }
}
If you were to compile all three classes and then delete the file Missing.class before running
Strange1 and Strange2 , you'd find that the two programs behave differently. One throws an
uncaught NoClassDefFoundError , whereas the other prints Got it! Which is which, and how can
you explain the difference in behavior?
Solution 44: Cutting Class
The Strange1 program mentions the missing type only within its try block, so you might expect it
to catch the NoClassDefFoundError and print Got it! The Strange2 program, on the other hand,
declares a variable of the missing type outside the try block, so you might expect the
NoClassDefFoundError generated there to be uncaught. If you tried running the programs, you saw
exactly the opposite behavior: Strange1 tHRows an uncaught NoClassDefFoundError , and
Strange2 prints Got it! What could explain this strange behavior?
If you look to the Java language specification to find out where the NoClassDefFoundError should
be thrown, you don't get much guidance. It says that the error may be thrown "at any point in the
program that (directly or indirectly) uses the type" [JLS 12.2.1]. When the VM invokes the main
method of Strange1 or Strange2 , the program is using class Missing indirectly, so either program
would be within its rights to throw the error at this point.
The answer to the puzzle, then, is that either program may exhibit either behavior, depending on the
implementation. But that doesn't explain why in practice these programs behave exactly opposite to
what you would naturally expect, on all Java implementations we know of. To find out why this is
so, we need to study the compiler-generated bytecode for these programs.
If you compare the bytecode for Strange1 and Strange2 , you'll find them nearly identical. Aside
from the class name, the only difference is the mapping of the catch parameter ex to a VM local
variable. Although the details of which program variables are assigned to which VM variables can
vary from compiler to compiler, they are unlikely to vary much for programs as simple as these.
Here is the code for Strange1.main as displayed by javap -c Strange1 :
 
 
Search WWH ::




Custom Search