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