Typically when writing Java applications, developers may wish to use existing libraries of native code, or call out to routines written in native code for performance reasons. The following gives an example (using the current native code interface provided by in the Sun Java VM) as to how this would be done.
In Java, example syntax for declaring a method which is implemented in native code is as follows:
package myPackage; class myClass { public static native int myMethod (myOtherClass myObj); }
This declares a static, native method named myMethod within the class myClass in the package myPackage. The method takes myObj (an object of type myOtherClass) as it's parameter.
This function can be then be called from within the Java code by invoking (for example):
... int i; myOtherClass myObj = new myOtherClass; i = myClass.myMethod (myObj); ...
In order to deal with the interfacing between Java and C, there is a program called javah (included in the JDK) which takes the above native declaration and produces two pieces of code from it.
The C native code implementation of the method, myMethod, would look something like:
int myPackage_myClass_myMethod (HObject *AlwaysNull, HmyOtherClass *myObj) { myOtherClass *mO = unhand (myObj); // body of the implementation of the function ... // e.g. mO->member; }
The function is defined with an initial first parameter (AlwaysNull) that is present only for historical reasons. It is always 0 in current Java VM implementations. Note that in the Microsoft Native Code Interface (below) we keep this convention for source code compatibility.
The stub (which javah generates) would look like this
Java_myPackage_myClass_myMethod_stub (ExecEnv *, paramblock * pPB);
When the function myMethod is called from Java, it is this stub which is called. The parameter block in that stub is unwrapped, pushed onto the stack, and then the myPackage_myClass_myMethod function is called in C. The java code passes the parameter block from the frame, the stubs unwrap it, and then they pass it on to the actual function that you're interested in calling.
The final piece to calling is the unhand macro used in the C function above. This relies on the internal object representation ( a double indirection between the myObj handle and the data - see below) to provide an actual pointer to the data in C. It is necessary to use the unhand macro in order to access the object data. It is recommended that unhand be used each time an object is accessed, as the object may have been garbage collected within Java, and a pointer reference to it obtained previously may then point to invalid data. Although existing VMs other than Microsoft's attempt to find and ensure validity of all unhanded object references in any C code which may have been called, there are cases where this attempt may not be sufficient to prevent pointers from becoming invalid.
The following diagram describes the internal storage details of objects within the existing native code system.
Essentially, everywhere that a reference to an object is stored, there is a pointer to the handle which then references the object.
The main consequences from these implications are loss in performance with native code (which is one of the reasons why native code is used in the first place) and potentially non-deterministic errors when unhand has been used unsafely.