Description of problem: The libguestfs Java bindings are buggy: they do not check for Java exceptions after all JNI calls that might throw them, and they do not acquire all needed `jclass`, `jmethodid`, and `jfieldid` objects during `JNI_OnLoad`. They also leak local references. Furthermore, potentially large objects are copied between Java and native, instead of using direct `ByteBuffer`s. Probably the easiest solution is to use `sun.misc.Unsafe`/`jdk.unsupported.misc.Unsafe` and friends to do all marshaling in Java.
I have to say I don't know very much about JNI. Do you have suggested patches or outline changes that need to be made?
* Firstly, any calls to `FindClass`, `Get*MethodID`, and other such methods (anything that returns a `jclass`, `jmethodid`, or a `jfieldid`) should be done in `JNI_OnLoad` and the `jclass` objects converted to global refs. * Java exceptions need to be checked (using `ExceptionCheck`) after every operation that might throw them, unless the function return code guarantees that there is no pending exception, or unless one is simply returning. * Local references must be released with `DeleteLocalRef` when no longer needed. If the number of local references may exceed 16, it is necessary to call `EnsureLocalCapacity` and check its return value. * Any data that is not of small and fixed size should be stored in direct `ByteBuffer`s on the Java side and accessed using `GetDirectBufferAddress` or (better yet) the corresponding call from `sun.misc.Unsafe`. It should be accessed from Java using the corresponding functions of `ByteBuffer` or `Unsafe`. This is the only way to avoid an O(n) copy on JVMs that do not support pinning (most of them) with native methods that might block (most of them). * Calling into native from Java is much, much faster than the reverse. Marshalling code should thus be in Java, rather than in C.