# Friday, 20 August 2004
« Article on IKVM | Main | New Snapshot »
Non-virtual Method Invocation

In Tuesday's snapshot I finally implemented the CallNonvirtualMethod JNI routines. I've never seen any JNI code that actually uses them, but I obviously needed to implement them at some point.

For those of you unfamiliar with these routines, let me explain them briefly. Normally when you call a virtual method, the runtime type of the instance the method is called on determines the actual method you end up at (so called virtual method dispatch), but these routines allow you to call a base class method as well. So, if you'd use CallNonvirtualObjectMethod on java.lang.Object.toString() on a java.lang.String instance (let's say “foo“), the result you'd get would be java.lang.String@17e809 instead of the string “foo“.

The CLR Reflection API doesn't have the ability to invoke a virtual method non-virtually. Unlike Java however, the CLR does allow the CIL call instruction to be used to call arbitrary methods non-virtually (the Java invokespecial method can only be used to call methods in the same class or in a base class). So the obvious way to implement these routines, would seem to be to dynamically emit some code that calls the requested method non-virtually, but there is problem with this approach, the JNI routines don't enforce accessibility (they allow you to call non-public methods) and the CLR enforces accessibility. I got around this by using RuntimeMethodHandle.GetFunctionPointer() incombination with the CIL calli instruction. This also has the advantage that the dynamically emitted stubs can be reused for methods with the same signature, because the target address isn't baked into the method, but passed in.

Non-orthogonality

While I don't have a very compelling use case for non-virtual method invocation through reflection, based on API orthogonality and completeness a case could be made for it, but more importantly, I think that ECMA/Microsoft should consider changing the CLI spec to allow non-verifiable code to bypass the accessibility checks. Note that the new DynamicMethod in Whidbey already allows accessibility checks to be bypassed (and note also that whoever wrote the doc for DynamicMethod doesn't understand the difference between visibility and accessibility).

The trick of using calli to bypass the accessibility checks doesn't work for virtual method invocation, because there is no way to dynamically and efficiently get the function pointer of a method by applying the virtual method dispatch rules (i.e. there is no dynamic equivalent of the CIL ldvirtftn instruction).

To summarize, here is what I think should be changed:

  • CLR shouldn't bother enforcing accessibility in non-verifiable code.
  • MethodInfo should get a new InvokeNonvirtual method.
  • MethodInfo should get a GetFunctionPointer(object) method that returns the method pointer that results from virtual dispatch.
Friday, 20 August 2004 09:11:25 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]