Compile it and then delete TestEx.class. What should happen ? In all of the 3 machines the NoClassDeffoundError (thrown on TestEx.class) was not caught at the 'catch (Throwable ee)' although to me it seems it should be.
mmm, seemed odd to me as well then then i read this:
* An <code>Error</code> is a subclass of <code>Throwable</code>
* that indicates serious problems that a reasonable application
* should not try to catch. Most such errors are abnormal conditions.
* The <code>ThreadDeath</code> error, though a "normal" condition,
* is also a subclass of <code>Error</code> because most applications
* should not try to catch it.
* <p>
* A method is not required to declare in its <code>throws</code>
* clause any subclasses of <code>Error</code> that might be thrown
* during the execution of the method but not caught, since these
* errors are abnormal conditions that should never occur.
from the source of Error.java, of which NoClassDefFoundError is a sub-class of.
To the 1st reply: This relates only to compile time issues. Unchecked exceptions, the user should not try to catch them but they COULD be catched.
Now, as far as the linkage error goes. Upon loading and linking Excp, the VM could find out the TestEx is missing (that is premature loading of TestEx, since it might never get used).
At the point where it reaches that linkage error, it should create an instance of NoClassDefFoundError and intilize it (statically and instance) and throw it.
Of course, putting Excp e = new Excp() inside the block will not change the semantics since those errors (linkage) should actually occur when resolving happens at run time, so I still think it should still throw an error.
then call java TestExcp you will see that the exception has been caught after deleting TestEx.class.
As to the whole thing about premature loading, I would suggest that you take a little time out to read the JVM specification, in particular the loading and linking section.
It is pretty clear that when a class is first loaded and linked, all classes that it refers to are loaded (but not necessarily linked) hence this error being thrown in an uncatchable manner in your example. The loading and linking of Excp occurs before the main method is called and this includes the load of the TestEx class.
I am clear about the loading and linking phases.
So this statement "...It is pretty clear that when a class is first loaded and linked, all classes that it refers to are loaded (but not necessarily linked)..."
it not necessarily true.
When a class is loaded, all superclasses/interfaces are loaded. The time of linking is not really specified. It could be early linking or late linking, specifically the resolving part of the linking phase, since that is the issue here (not the verification or preparation). A VM should always make sure it looks like late resolving since a statement that could create error might never be executed.
In most cases, the VM does not try and should not to load all classes in constant pool when it does the linking phase. It should do so when that class is resolved (on the many bytecodes that do so).
So the case above. Yes, when Excp is loaded and linked it could preload TestEx, but this is not really relevant here. Next, when the 'new' bytecode is executed in test() on TestEx, it knows the TestEx is missing and at this point it must create NoClassDefFoundError instance and throw it. Up to here the behavior is clear.
What happens after the new is executed and now we know we have NoClassDefFoundError, what happens now is the question. The user might still want to handle this exception. Of course it is quite rare, but should be possible.
I tried it on 3 different machines but the result is
the same
Did you try it with different JVMs, or the same JVM on different machines? - I have just tested on Windows using Sun's 1.4.1 VM and IBM's VM bundled with Eclipse 2, and both caught the error fine.
I am clear about the loading and linking phases.
So this statement "...It is pretty clear that when a
class is first loaded and linked, all classes that it
refers to are loaded (but not necessarily linked)..."
it not necessarily true.
If you try to add an ee.printStackTrace() to the TestExcp class that bob_boothby posted, you will see that the noclassdeffound-error originates from the line
I tried it with Jdk 1.3 on Win 2000, then tried it with Mnemonics JVM for win 2000, then with the GCC gij for Linux. None of them managed to catch it.
About the stack trace, this is interesting. But I do not think is relevant. Where the error has been detected is not that important. It should be caught regardless. There is a mention in the lang and vm spec about unchecked exception, to which NoClassDefFoundError belongs, but this is all compile time constraints, not run time.
If you try to add an ee.printStackTrace() to the
TestExcp class that bob_boothby posted, you will see
that the noclassdeffound-error originates from the
line
I'm no expert on loading and linking (in fact I know very little about it), so I don't know what is correct here, but I always would have expected the behaviour that martinvv is expecting.
Anyway, I just ran my test again, and having added ee.printStackTrace(), the exception originates from the line throw new TestEx() in both environments.
I changed the code to that posted by bob_boothby, added ee.printStackTrace(), and again the exception originates from the line throw new TestEx() in both environments.
About the stack trace, this is interesting. But I do
not think is relevant. Where the error has been
detected is not that important. It should be caught
regardless.
Ehhm. The question posed by the original poster was why the NoClassDefFoundError wasn't caught by a specific try/catch-block. As some people have said, and the stacktrace demonstrates, the NoClassDefFoundError is thrown before that block is ever reached.
You might of course argue that the jvm should catch the error more gracefully, but I can't see how that can be done.
I am not sure what you mean by "how that can be done". According to all specifications it should catch the error in the main method of the main program. I am thinking if anyone has a reference to some line in the documentation that we might be missing, that would be great.
Actually that program came out, because I was thinking what should happen when exception happens during 'athrow', i.e. during resolving.
I'm trying to work out where in the specs. it says that it should behave as you stated. I suppose as usual it comes down to interpretation of the specs.:
I would read this paragraph of the spec (5.4.3 Resolution) as giving them an out...
Linking exceptions generated by checks that are specific to the execution of a particular Java virtual machine instruction are given in the description of that instruction and are not covered in this general discussion of resolution. Note that such exceptions, although described as part of the execution of Java virtual machine instructions rather than resolution, are still properly considered failure of resolution.