Access to C ++ - memory from a Java application

I have a C ++ application that calls some java functions. I am using JNI. Everything is working fine, but still there is one small problem. In a C ++ application, I have several huge arrays. The Java App also needs this data and returns one huge array of results. I am currently just copying the data (you can check some world of code below). And it would be much better if I accessed these arrays from a Java application directly by pointer. Is it possible? I suppose not (because of the JVM), but in this case I have to explain it to my boss in detail :) So, yes or no, and how and why?

jdoubleArray in2 = env->NewDoubleArray(1000); jdouble *elems2 = (jdouble*)calloc(1000, sizeof(jdouble)); for(int i = 0; i < 1000; i++) { elems2[i] = (jdouble)inputArray[i]; } env->SetDoubleArrayRegion(in2, 0, 1000, elems2); if(midCD != NULL) { jdouble res1 = env->CallStaticDoubleMethod(cls, midCD, in2); double res1c = res1; printf("C++.Res1: %f\n", res1c); } 
+4
source share
2 answers

The best you can do is use the Get <PrimitiveType> ArrayElements Procedures . Hope VM supports pinning :

 jdoubleArray in2 = env->NewDoubleArray(1000); jboolean isCopy; jdouble *elems2 = env->GetDoubleArrayElements(in2, &isCopy); for(int i = 0; i < 1000; i++) { elems2[i] = (jdouble)inputArray[i]; } env->ReleaseDoubleArrayElements(in2, elems2, 0); elems2 = NULL; 

If isCopy is JNI_FALSE after calling GetDoubleArrayElements (), then no copy was made.

EDIT: After reading your question again, you may consider implementing the Archie idea . It depends on how your Java methods use the data. If Java methods do not use the entire array, or not all at once, then the Archie solution to create a Java class wrapper from a C ++ array using its own accessories can be a good solution. If, however, the Java method requires all the data, then you might need the fastest way to get the data into the VM that GetDoubleArrayElements () provides.

If you make changes to some elements of a C ++ array and want to make the same changes to a copy of Java that SetDoubleArrayRegion () comes into play.

EDIT2: I believe Archie is referring to something like:

 public class NativeDoubleArrayProxy { // This is the native `inputArray' pointer. private long p; private int length; private NativeDoubleArrayProxy(long p, int length) { this.p = p; this.length = length; } public int length() { return length; } public native double getDouble(int index); public native void getDoubles(int startingIndex, double[] out, int outOffset, int length); } 

The exact data depends on the type of your inputArray (is it an array of source C-types or std::vector<double> , something else?). But the idea is to build a NativeDoubleArrayProxy object on the JNI side, passing it the pointer passed to jlong . JNI implementations for getDouble () and getDoubles () implement copy code from C ++ to Java.

Of course, you need to be very careful to make sure that the pointer remains valid.

See also: What is the correct way to store an inline pointer inside a Java object?

+1
source

Direct ByteBuffers were introduced in Java 1.4 for this purpose. Along with the new classes on the Java side, there were corresponding JNI functions . You can wrap your own arrays in ByteBuffer (and the corresponding IntBuffer, etc.), and also read and write without copying.

+3
source

All Articles