Continue to see when the various checks that are required to run a Java program are in place. This time we'll look at the problem of interface invocation.
In the current JVM specification, there are 4 instructions associated with the method invocation: Invokevirtual, Invokeinterface, Invokestatic, and invokespecial. The JVM directive used when calling an interface method is invokeinterface. This instruction has a significant difference from the other 3 method invocation instructions: It does not require the JVM's validator (verifier) to check the type of the called object (Receiver), and the other 3 method invocation directives require the checksum to be invoked. That is, if the invoked object does not implement the specified interface when using Invokeinterface, it should throw an exception at run time rather than link, while the other 3 method invocation directives require an exception to be thrown when linking.
Look at what the JVM spec says:
Java Virtual Machine specification, 2nd Edition wrote
Invokeinterface
...
Runtime exceptions
...
If the class of objectref does not implement the resolved interface, Invokeinterface throws a Incompatibleclasschangeerro R.
Notice that the other 3 method invocation instructions "Incompatibleclasschangeerror" are linking Exception instead of runtime Exception.
The behavior that is visible to Java programs is that if a method fails the checksum, the entire method is not executed, and if a Run-time exception can be thrown through a checksum, the portion of the method before the exception is thrown will be executed.
Of course, the programs we write directly in the Java language are difficult to raise because the Java compiler checks to ensure a certain level of type safety. But Java class files, or Java bytecode, can be generated by other than the Java compiler, where the Java compiler is not guaranteed for type safety, but relies on the JVM's checksum of bytecode and run-time checks.
I noticed this feature of Invokeinterface before I read John Rose's invokedynamic to JSR 292. John specifically mentions that invokedynamic, like Invokeinterface, does not check the type of the object being invoked at checksum. But I've never seen it before. Calling an interface method on an object that does not implement an interface is actually what it is.
OK, let's take a look at this one. First, create an interface IFoo, a class Fooimpl that implements the interface, and a class bar that does not implement the interface:
Ifoo.java:
Java code
Public interface IFoo {
void method ();
}
Fooimpl.java:
Java code
public class Fooimpl implements IFoo {public
void method () {
System.out.println ("Fooimpl.method ()");
}