Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java JNI - associating resources allocated in C with java objects?

I want to allocate some memory in C and keep it associated with a java object instance, like this:

void configure(JNIEnv *object, jobject obj, ....) {
  char *buf = new char[1024];
  // associated <buf> with <obj> somehow
}

And then later free the memory when the java object gets garbage collected - I could do this by calling a JNI function from the finalize() method of the java object.

The question is, how do I associate a C pointer with the java object? Keep a long field in the object and cast the pointer to long? Is there a better way?

like image 456
Viktor Avatar asked Jan 04 '10 07:01

Viktor


People also ask

Does JNI make Java code machine dependent?

JNI = Java Native Interface. Native = platform dependent. JNI is optional and very specialized part of Java, you are not forced to use it for any of your Java coding. JNI is meant to be used for isolated tasks which absolutely cannot be done in JVM.

How does JNI work in Java?

It defines a way for the bytecode that Android compiles from managed code (written in the Java or Kotlin programming languages) to interact with native code (written in C/C++). JNI is vendor-neutral, has support for loading code from dynamic shared libraries, and while cumbersome at times is reasonably efficient.

What is a JNI method?

JNI is an interface that allows Java to interact with code written in another language. Motivation for JNI is code reusability and performance. WIth JNI, you can reuse existing/legacy code with Java (mostly C/C++).

What is Jclass in JNI?

The jclass instance is your object on which a method will be invoked; you'll need to look up the getName method ID on the Class class, then invoke it on the jclass instance using CallObjectMethod to obtain a jstring result. So in short yes, you just call the getName function and look at the jstring result.


1 Answers

Generally, if you want to transfer a pointer from C to Java, it's recommended to use long so that there are enough bits to hold the pointer value in case the platform is 64 bits.

Then, have a look at ByteBuffer.allocateDirect() which creates a ByteBuffer instance which memory can be shared with C. You can allocate such a direct ByteBuffer from the Java side then pass it as a jobject to a JNI function and inside this JNI function you use the GetDirectBufferAddress function.

Another way is to wrap a native area of memory with the NewDirectByteBuffer JNI function from the native side. It gives you a jobject you pass back to the Java side (pay attention to local and global references). Pay attention to the fact that once the direct ByteBuffer that wraps the native memory has been created, you are still responsible for managing the native memory: at some point, you will have to call delete buf; in your native code, Java won't do it for you.

like image 74
Gregory Pakosz Avatar answered Nov 05 '22 18:11

Gregory Pakosz