No-throw VirtualMachineError guarantees
Quoth the Java Virtual Machine Specification:
This specification cannot predict where internal errors or resource
limitations may be encountered and does not mandate precisely when
they can be reported. Thus, any of theVirtualMachineError
subclasses
defined below may be thrown at any time during the operation of the
Java virtual machine:
In Java therefore no exception guarantees can be made with respect to VirtualMachineError
exceptions. All exception guarantees must be subject to the qualification "... but not if a VirtualMachineError
is thrown". This is one of the ways in which Java is different from C++.
This also suggests that there is not much point in catching a VirtualMachineError
exception, because the program is in an undefined state if one has been thrown. That unfortunately includes OutOfMemoryError
exceptions. Unfortunate, because if a program has several independent tasks to perform (for example, a web server), if one task fails because it needs too much memory, we might want to continue with the other tasks.
Which JVM instructions cannot throw?
You are asking the wrong question. If you expect a VirtualMachineError
to be thrown, you can’t expect the behavior to be guaranteed to stay the same, regardless of whether there is a try … catch
or not.
To stay at your example:
try { return 1; }
catch (Throwable t) { return 2; }
For this code, there will be an exception handler for the two byte code instructions iload_1
, ireturn
. This implies that if a VirtualMachineError
is raised right before the iload_1
instruction or right after the JVM encountered the ireturn
instruction, the error won’t be catched. And nobody can tell apart that situation from the situation when the the exception handler has been removed and the error is raised in-between these instructions.
Compare with The Java® Virtual Machine Specification, Java SE 8 Edition §2.10. Exceptions:
A Java Virtual Machine may permit a small but bounded amount of execution to occur before an asynchronous exception is thrown. This delay is permitted to allow optimized code to detect and throw these exceptions at points where it is practical to handle them while obeying the semantics of the Java programming language.
So for the case of the VirtualMachineError
, the absence of the exception handler would make no difference, no one can notice it and the JVM might defer the error anyway depending on the internal state of code optimization. A different case is the possibility of ireturn
throwing an IllegalMonitorStateException
.
After all, the question is what you are going to optimize. Exception handlers normally have no performance impact as the JVM doesn’t touch them as long as no exception is there to be handled.
What operations may (not) throw StackOverflowError?
is it true that code which do not call any functions will never throw a
java.lang.StackOverflowError?
A StackOverflowError
is-a VirtualMachineError
. It transpires that there are no no-throw guarantees about VirtualMachineError
s. The Java Virtual Machine Specification says the following (emphasis added).
This specification cannot predict where internal errors or resource limitations may
be encountered and does not mandate precisely when they can be reported. Thus,
any of the VirtualMachineError subclasses defined below may be thrown at
any time during the operation of the Java virtual machine:
...
StackOverflowError
Which Java Errors and Exceptions may (not) be thrown by empty statements?
This question is very similar to the other question you posted. I think I'll try to address both questions here.
Since you refer to the JVMS I'll assume that you're after a formal answer, and the formal answer is that your question(s) doesn't really make sense. :-)
Asking how the JVM will execute a snippet of Java source code is like asking a mathematician the correct way of computing 10+10. The mathematician will probably say something like "how to compute it is not defined". Similarly, the JLS that defines the meaning of the Java snippet does not go into specifics of how to execute it.
So, first let me formalize your question slightly: "Where in the bytecode (emitted by the reference implementation of javac
) corresponding to the given Java snippets could VirtualMachineErrors
occur?"
This question is arguably much simpler to answer. The relevant section of the JVMS says
A Java Virtual Machine implementation throws an object that is an instance of a subclass of the class
VirtualMethodError
when an internal error or resource limitation prevents it from implementing the semantics described in this chapter. This specification cannot predict where internal errors or resource limitations may be encountered and does not mandate precisely when they can be reported.
Thus, the answer is: Between any two bytecode instructions.
Now to return to your original question: This snippet for instance
try {
// nothing
} catch (java.lang.Throwable e) {
// which Throwable subclass might we see?
}
is compiled to the empty program, which can't reasonably throw any exceptions.
Regarding your follow up question in a comment:
Should JLS 11.1.3 be read as "subclasses of
Throwable
are guaranteed not to appear between bytecode unless it is a subclass ofVirtualMachineError
"?
Yes, you could put it like that. I would perhaps have worded it a bit differently: Any instruction can give rise to
- the exceptions specified by the JVM Instruction set for the instruction in question,
- any exception of type
VirtualMachineError
- and no other exceptions
Get “Could not create the Java virtual machine” error running StarTeam 2008 Release 2 client
Rather than being a problem locating the Java Virtual Machine, as I’d previously thought, turns out it’s a memory allocation issue.
In StarTeamCP.stjava, the default option set is -Xmx1024m
. My machine doesn’t have a gig of RAM to spare for a Java VM, hence the error.
By setting it to -Xmx512m
, I was able to get up and running.
See also my blog entry about this.
Why is it possible to recover from a StackOverflowError?
When the stack overflows and StackOverflowError
is thrown, the usual exception handling unwinds the stack. Unwinding the stack means:
- abort the execution of the currently active function
- delete its stack frame, proceed with the calling function
- abort the execution of the caller
- delete its stack frame, proceed with the calling function
- and so on...
... until the exception is caught. This is normal (in fact, necessary) and independent of which exception is thrown and why. Since you catch the exception outside of the first call to foo()
, the thousands of foo
stack frames that filled the stack have all been unwound and most of the stack is free to be used again.
Can I prevent java from throwing certain exceptions?
A distinction must be drawn between checked and unchecked exceptions to answer this question:
If a method does not declare that it throws a checked exception, it cannot throw an exception of that type (or one of its subtypes):
void doSomething() {
throw new Exception(); // Illegal, without throws Exception on doSomething();
}As such, you know that a checked exception is not thrown by a method if it is not declared throwing that exception.
Checked exceptions are intended to be caught, since they are supposed to indicate conditions from which you can recover, so you need to know that they occurred. e.g.
IOException
: if you try again later, the file might exist, the disk might have space on it, the network might be back up (etc).A method can throw an unchecked exception without declaring that it does; but similarly, you don't need to put in any work to catch it if you don't want to (e.g. because you know that it cannot possibly be thrown). As such, you can never guarantee that a particular
RuntimeException
is not thrown by a method - maybe it's not thrown directly by the method you called, but it could be thrown by a method that calls (now or in future implementations).Unchecked exceptions are not really intended to be caught, since they are supposed to indicate unrecoverable errors, like programming errors. e.g.
NullPointerException
: you can call the same method with the same parameters, but it'll still fail, because you're running the same code.
Related Topics
Is Java.Util.Date Using Timezone
What Is the Cross-Platform Way of Obtaining the Path to the Local Application Data Directory
Hiding Instance Variables of a Class
How to Get Data Between Quotes in Java
Running Rmi Server, Classnotfound
Custom JSON Deserializer Using Gson
Java Regular Expression to Extract Content Within Square Brackets
Adding Image to Jbutton with Foreground Label
No-Throw Virtualmachineerror Guarantees
Missing Return Statement for If/Else Statement
Why Business Logic Should Be Moved Out of Jsp
Calendar Returns Date in Wrong Time Zone
How to Simulate a Buffered Peripheral Device with Swingworker
The Method Getdispatchertype() Is Undefined for the Type Httpservletrequest
Applying Map of the Earth Texture a Sphere
How to Get the Latest Jre/Jdk as a Zip File Rather Than Exe or Msi Installer