What Does a Jvm Have to Do When Calling a Native Method

What does a JVM have to do when calling a native method?

Calling a JNI method from Java is rather expensive comparing to a simple C function call.
HotSpot typically performs most of the following steps to invoke a JNI method:

  1. Create a stack frame.
  2. Move arguments to proper register or stack locations according to ABI.
  3. Wrap object references to JNI handles.
  4. Obtain JNIEnv* and jclass for static methods and pass them as additional arguments.
  5. Check if should call method_entry trace function.
  6. Lock an object monitor if the method is synchronized.
  7. Check if the native function is linked already. Function lookup and linking is performed lazily.
  8. Switch thread from in_java to in_native state.
  9. Call the native function
  10. Check if safepoint is needed.
  11. Return thread to in_java state.
  12. Unlock monitor if locked.
  13. Notify method_exit.
  14. Unwrap object result and reset JNI handles block.
  15. Handle JNI exceptions.
  16. Remove the stack frame.

The source code for this procedure can be found at SharedRuntime::generate_native_wrapper.

As you can see, an overhead may be significant. But in many cases most of the above steps are not necessary. For example, if a native method just performs some encoding/decoding on a byte array and does not throw any exceptions nor it calls other JNI functions. For these cases HotSpot has a non-standard (and not known) convention called Critical Natives, discussed here.

Does JVM halt when calling native code?

Threads running native code will not halt JVM.

As soon as JNI method is called, Java thread switches to _thread_in_native state. Threads in this state are not counted during safepoint operations, i.e. when a stop-the-world event occurs (like garbage collection), JVM does not stop these threads. Conversely, threads in native state cannot stop JVM unless they perform a JNI upcall. When a native method returns, the thread switches back to _thread_in_Java state.

JNI How to call java and call back native, And how to get JVM std io

To access native methods, you still must call System.LoadLibrary(). The spec explains that your Driver.java should look contain:

public class Driver {
static { System.loadLibrary("driver"); } // this name must be matched!
public static native int nativeSum(int a, int b);

public static int sum(int a, int b) {
return nativeSum(a, b);
}
}

and in your main.cpp,

extern "C" JNIEXPORT jint JNICALL Java_Driver_nativeSum(JNIEnv*, jclass, jint a, jint b) {
std::cout << "Native invoked " << std::endl;
return a + b;
}

extern "C" JNIEXPORT jint JNI_OnLoad_driver // this suffix must match the name used in Java
(JavaVM *vm, void *reserved) {
std::cout << "Native loaded" << std::endl;
return JNI_VERSION_1_8;
}

Make sure that the linker keeps both Java_Driver_nativeSum and JNI_OnLoad_driver exported in your binary.

As for your first question, there is no separate JVM stdio stream, Java reads from the same fd=0 and writes to same fd=1 as all others.

Calling built-in java native methods

No you can't. It's designed that way on purpose; you would override the API contracts if you could.

In any event, the standard library wrapper code is very slight and with JIT compilers you shouldn't notice any speed impact.

Furthermore, the implementation of those methods are not part of the API spec. What is "native" for one implementation of Java doesn't have to be for another.

Can one native method be called from another native method?

Calling one native method from another is in fact permitted. At least, I did not receive any errors or warnings when I did this. But the call must include the full function name as expected of any native method - i.e. Java_com_project_package_JSQ_destroy and the parameters should include:

  1. the JNI environment
  2. jobject Object
  3. parameters expected by the method. In this case, shdl

Therefore, the call must be like so:

Java_com_project_package_JSQ_destroy(env, <jobject_object_name>, shdl);

It should place the call to destroy method. However, it doesn't really adhere to the purpose served by the Java Native Interface which is a layer used to allow Java code to make calls to and be called by native applications and libraries written in other languages (here, C++).



Related Topics



Leave a reply



Submit