0

I am developing a JNI application. However JNINativeInterface_ * inside the struct struct JNIEnv_ is null, hence causing any call for JNI (example : env->NewStringUTF(...)) functions to throw a segmentation fault error. JNIEnv_ struct looks like this :

struct JNIEnv_ {
    const struct JNINativeInterface_ *functions;
.
.
.

I honestly dont know how to fix this, as I think java is supposed to fill this when you make a call to System.loadLibrary(...). I appreciate any help.

Ozum Safa
  • 1,458
  • 2
  • 15
  • 27
  • When you load the library in Java, JNI makes sure that a valid `env` to be provided. You have to use the JNI that is provided to you in the native function call. – Christophe Jun 29 '15 at 19:17

1 Answers1

0

Two possibilities:

1) Your C++ code is called from Java as native function:

For example:

JNIEXPORT void JNICALL Java_MyJNative_doSomething(JNIEnv *env, jobject jo)
{
    std::cout << "doSomething() : ";
}

The JNIEnv* pointer is given to you by the Java environment.

2) Your C++ code calls the Java code via JNI:

In this case you have to setup a JavaVM* and JNIEnv* pointer, following the JNI invocation logic. See for example this article.

A special case to be mentionned, if you have already invoked JNIEnv* but you work with multiple threads on C++ side. Then every thread has to attach to the JNIEnv* using:

JNIEnv *env;                // Pointer to native interface
jint rc = jvm->AttachCurrentThread ((void **)&env, nullptr);  // Attach without addutiobal parameters
                            // where jvm is a valid JavaVM*
Christophe
  • 68,716
  • 7
  • 72
  • 138
  • It is actually a mixture of the both. Java calls C++, registering C++ callbacks to an event in which some java methods will be ran. But as you have said, all these are done within other threads that are created within C++. This probably requires attachment as you have proposed ? – Ozum Safa Jun 29 '15 at 19:46
  • I would like to add that the jvm runs first, so I dont think i can create a new JVM in c++, that would not help. How could I get the existing jvm? – Ozum Safa Jun 29 '15 at 20:23
  • If the threads are created on Java side, the env received by C++ are the right ones. If the threads are created in C++, you have indeed to attach them to the jvm. If you don't have the jvm, you can do: `JavaVM* jvm; env->GetJavaVM(&jvm);` – Christophe Jun 29 '15 at 20:42
  • Is exporting `JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved)` a way to acquire javaVM, or am I better of just getting JavaVM from env and save it to a global C++ pointer of type `JavaVM` ? – Ozum Safa Jun 29 '15 at 20:48
  • Also, I cant quite grasp how those C++ threads cant access a globally saved JNIEnv pointer's address. Are the heaps separate or something ? – Ozum Safa Jun 29 '15 at 20:52
  • There is in fact [thread local storage](http://stackoverflow.com/questions/11983875/what-does-the-thread-local-mean-in-c11) and here some more infos about [C++ threads in JNI context](http://stackoverflow.com/questions/9642506/jni-attach-detach-thread-memory-management) – Christophe Jun 29 '15 at 21:00