I need to start a new thread from native part of android application. It must be declared and defined in JNI. Does someone know how can I do it? If someone will post the example I would be very happy.
The JNI interface pointer (JNIEnv *) is only valid in the current thread. You must not pass the interface pointer from one thread to another, or cache an interface pointer and use it in multiple threads.
JNI is the Java Native Interface. 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 just the way that Java handles calling into native/C++ code, and calling back into Java from there. It has nothing to say about Android - it is a Java language feature. The Android NDK is a way to write Android applications using code called by JNI.
JNIEnv – a structure containing methods that we can use our native code to access Java elements. JavaVM – a structure that lets us manipulate a running JVM (or even start a new one) adding threads to it, destroying it, etc…
Easiest way is to use C++11 thread class. See this topic on how to enable C++11 with Android NDK. Also see this post if you are having problems getting thread class to work. Then you can use it like this:
#include <thread> // std::thread
void foo()
{
// do stuff...
}
void bar(int x)
{
// do stuff...
}
JNIEXPORT void JNICALL
Java_org_testjni_android_Game_someFunction(JNIEnv * env, jobject obj)
{
std::thread first (foo); // spawn new thread that calls foo()
std::thread second (bar,0); // spawn new thread that calls bar(0)
//main, foo and bar now execute concurrently
// synchronize threads:
first.join(); // pauses until first finishes
second.join(); // pauses until second finishes
}
If you can't use C++11, just use pthread (POSIX thread), which isn't much different, except it's like old C:
#include <pthread.h>
//This function will be called from a thread
void *call_from_thread(void *) {
//do stuff
return NULL;
}
JNIEXPORT void JNICALL
Java_org_testjni_android_Game_someFunction(JNIEnv * env, jobject obj)
{
pthread_t t;
//Launch a thread
pthread_create(&t, NULL, call_from_thread, NULL);
//Join the thread with the main thread
pthread_join(t, NULL);
}
Here's some more info on using POSIX threads with Android.
Also you will need to look up how to bind the JNIEnv pointer to the current thread if you want to use it in any thread but the one the JNI function is called from. From the JNI spec:
Creating the VM
The JNI_CreateJavaVM() function loads and initializes a Java VM and returns a pointer to the JNI interface pointer. The thread that called JNI_CreateJavaVM() is considered to be the main thread.
Attaching to the VM
The JNI interface pointer (JNIEnv) is valid only in the current thread. Should another thread need to access the Java VM, it must first call AttachCurrentThread() to attach itself to the VM and obtain a JNI interface pointer. Once attached to the VM, a native thread works just like an ordinary Java thread running inside a native method. The native thread remains attached to the VM until it calls DetachCurrentThread() to detach itself.
The attached thread should have enough stack space to perform a reasonable amount of work. The allocation of stack space per thread is operating system-specific. For example, using pthreads, the stack size can be specified in the pthread_attr_t argument to pthread_create.
Detaching from the VM
A native thread attached to the VM must call DetachCurrentThread() to detach itself before exiting. A thread cannot detach itself if there are Java methods on the call stack.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With