Assumtion
I assume you have the C++ Code compiled for Android by using a tool set like Android NDK and the front end Java app is running on the same device as the back end C++ code.
Java Native Calls and Session State
No matter which of the three following interfaces you use. The C/C++ Libraries are loaded and stay in memory the whole time then Java application is running. The state of the library will be preserved the whole time. I don't clearly get the concern you have about initialization. It's not like starting a command on a CLI, where the other application is started and stopped over and over.
... But main problem for me, is that C++ components are pretty heavy (tokenizers, vectorizers, corpus data, etc) and I can't recreate them on every call ...
Loading Native Libraries in Java
There are some ways to load native libraries in Java, I want to point out three:
JNI - Java Native Interface
JNI is a tool as old as Java itself. System calls from SWT were created using JNI. JNI is not the easy way, you have to define the functions/methods you want to make in Java as native, compile them to a C/C++ header, write the code for calling your library in this intermediate library. Compile this code for every ABI Platform (There are 7 Androids ABIs according to NDK). In the Java program you have find out the platform to call the ABI suitable intermediate library. JNI has many other pitfalls.
JNA - Java Native Access
[JNA] is a java library that dynamically loads the C/C++ library by reflection. The definition of the Java call is done in pure java with no extra tool. The ease of usage has a trade-off in performance, the overhead of calling a function is up to 10 times slower than JNI. But that only plays a roll if you are calling extreme short running C/C++ library functions/methods very often. In your case it sound like you just call a few time the functions and these functions will take there time to run. JNA is used by Android developers.
JNR-FFI - Java Native Runtime
JNR-FFI is the newest candidate. JNR-FFI is the part you use to call libraries.The other parts are the baseline for JNR-FFI. It's very much inspired by JNA. Java code developed with JNA and with JNR-FFI looks very similar. The reason JNR-FFI was developed is performance. In general JNR-FFI is a little slower than JNI (for getpid approx. 15%) but under some circumstances it can be faster than JNI. In the case of a long runtime on the C/C++ side this overhead does not matter. JNR is proposed to be in Java 9 as Standard Library JEP 191: Foreign Function Interface. The caveats: JNR-FFI seams to have some problems with Android.
Personal Experience
I had to implement some native library calls from Java. I started with JNI and after a week of testing an studying there were only few demo lines that worked. Every try took a long time, different tools, long building time. Than I found a presentation about the pitfalls of JNI and what side effects had to be considered. ...
I found JNA. Within a few hours the first demo code with my library worked and compared to JNI it is so lightweight and fast in development. I switched to JNR-FFI because it was the modern version of JNA. For what I did the performance was not the reason to switch, it was only a positive side effect.
I did not develop with JNA or JNR-FFI under Android. But in your case I would give JNA a try, because it is better supported with Android. I hopefully JNR-FFI gets implemented in Java 9 it is ease to switch from JNA code to a JNR-FFI code.
Example
I added and example of JNR-FFI to give you an idea of the ease of use. There is nothing more to do than to implement this few lines to be able to call a native c-library function.
JNR-FFI Example taken from Java Native Runtime - The Missing Link by Charles Oliver Nutter
public class GetPidJNRExample {
public interface GetPid {
@IgnoreError
long getpid();
}
public static void main( String[] args ) {
LibraryLoader<GetPid> loader =
FFIProvider
.getSystemProvider()
.createLibraryLoader(GetPid.class);
GetPid getpid = loader.load("c");
getpid.getpid();
}
}