How to avoid copying data between Java and Native C ++ Code

I am writing a library in C ++ that will be used by various Android applications to process data organized as a two-dimensional storage, where each dimension has no predefined size limits (for example, an array of floats and the size of the arrays to be quite large).

The current solution uses SWIG to copy data from memory allocated by Java code to C ++ structures. It turns out every float value array (in Java) became a float vector (in C ++).

The problem is that duplicating large amounts of data increases the risk of not running out of memory available to the application. I understand that in any case, the memory consumption problem should be resolved by limiting the amount of input, but the library does not know how much memory is available and must have integer data (accessing any data item takes multiple times) for it to be processed correctly.

So now I am considering using the same data store for Java and C ++, so the C ++ code requires direct access to the data stored in the Java code into the memory allocated on the Java side (memory allocated by the C ++ code , as a single repository is not considered).

I want to know how to organize such a memory exchange in a safe manner (preferably with SWIG).

I feel that there may be some difficulties with such an implementation, for example. with the Java garbage collector (C ++ code can access a store that is already freed) and slows down memory access through the shell (as mentioned earlier, the library requires re-accessing each data item) ... but maybe someone- it will advise me on a reliable solution. An explanation of why my idea is wrong can be accepted if it is supported by sufficient and convincing arguments.

+3


source to share


1 answer


You can access the raw dataset using Critical Native . This tecknology allows direct access to jvm memory without the need to transfer data between Java and native code.

But this has the following limitations :

  • must be static and not syncronized;
  • argument types must be primitive or primitive arrays;
  • the implementation must not call JNI functions, i.e. cannot allocate Java objects or throw exceptions;
  • should not run for a long time as it will block the GC while it is running.


Declaring a critical native declaration looks like a regular JNI method, except that:

  • starts with JavaCritical_

    instead of Java_

    ;
  • it has no additional arguments JNIEnv*

    and jclass

    ;
  • Java arrays are passed on two arguments, the first is the length of the array and the second is a pointer to the raw data of the array. That is, you do not need to call GetArrayElements

    friends, you can immediately use a direct array pointer.

Check out the original answer and the original article for details.

+1


source







All Articles