How to use JNI_GetCreatedJavaVMs in C++ to call Java Code

Surya Prakash Reddy

I have an Android application which contains the Java and C++ code. The C++ code I have is bundled into different .so files and can be invoked either from Java or other .so files. From some of the .so files, I need to call some Java code.

To call Java code, I see that we need JNIEnv. This can be received either when JNI_OnLoad method is called when library is loaded or when Java is calling C++ code, the JNIEnv is passed in method arguments. To call Java code, the recommended approach seems to be to save JNIEnv and use it later when calling Java code.

But in my case, I would like to keep my .so files generic so that they can be used across different OSs. So I don't want JNIEnv to be passed across multiple dependencies. What I am looking for is to get JNIEnv on demand.

I see that I can do this by getting JVM using JNI_GetCreatedJavaVMs method and then use the JVM instance to get the JNIEnv. The problem is this method doesn't seem to be defined in jni.h but only declaration was provided something like this:

    /*
     * VM initialization functions.
     *
     * Note these are the only symbols exported for JNI by the VM.
     */
    jint JNI_GetDefaultJavaVMInitArgs(void*);
    jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
    jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);

I understand that these should be loaded from other libraries but couldn't find any documentation on what libraries I need to import, what header/sources files I need to import in my C++ files and how I can use that method. Can anyone help with this?

I found this GitHub issue which says that these methods are not exported earlier and now exported only from API level 31. But it's not clear to me on how these exported methods should be accessed.

I am using r18b of NDK to build my code and when I try to use JNI_GetCreatedJavaVMs, it throws the following error:

  [x86_64] SharedLibrary  : libJniPoc.so
  /workplace/alias/workspace/src/JniPoc/src/main/cpp/core/InfoProvider.cpp:16: error: undefined reference to 'JNI_GetCreatedJavaVMs'
  clang++: error: linker command failed with exit code 1 (use -v to see invocation)
  make: *** [/workplace/alias/workspace/build/JniPoc/JniPoc-1.0/AL2_x86_64/DEV.STD.PTHREAD/build/intermediates/ndkBuild/debug/obj/local/x86_64/libJniPoc.so] Error 1

So what do I need to do compilation work and what do I need to make it work during runtime?

Botje

If you target API level 31 or up, the function is there so you do not need to do anything. According to apilevels.com you need to target version 31 anyway if you want to ship your app on the app store. The only thing you need to do is link with libnativehelper, which you can do by:

target_link_libraries(JniPoc PUBLIC -lnativehelper)

If that is not an option for whatever reason, you can create your own definition. As you noted, the JNI_Onload function receives a JavaVM argument, so you can stash it somewhere safe:

static JavaVM *g_vm = nullptr;
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
  g_vm = vm;
  // other code
}

JNIEXPORT jint JNICALL
JNI_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs) {
  if (bufLen < 1) {
    return JNI_ERR;
  }

  if (!g_vm) {
    *nVMs = 0;
  } else {
    *nVMs = 1;
    vmBuf[0] = g_vm;
  }
  return JNI_OK;
}

Note that this is only a partial solution, I am not sure what it will do on devices that are 31 and up. You could try adding __attribute__((weak)) to the definition but that is only a guess.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Java

How to Use Eclipse to Debug JNI code (Java & C/C++)

From Java

Rewrite C code in Java or use JNI?

From Dev

How to use QAndroidJniObject to call Java code from inside Qt?

From Java

Use JNI instead of JNA to call native code?

From Java

How do I call C functions from Java code on Linux

From Dev

How to call a function with arguments in C++ from JAVA using JNI?

From Dev

How to use java to call C# Library that call a native C++ library

From Dev

Why is it I can use C++ code in a library and call from a C program. How does that work?

From Dev

Use JNI to call C functions in host binary

From Java

How to pass C structs back and forth to Java code in JNI?

From Dev

How to debug native jni c++ code in eclipse with java project

From Dev

When using JNI to port in existing C++ code, use C or C++ to interface with JAVA?

From Java

Can C++ call Java code?

From Dev

How can use CFFI to call an existing C function given the source code?

From Java

JNI: From C code to Java and JNI

From Dev

C++ Multithread Java JNI method Call

From Java

How to use labels in java code?

From Java

How to use Parcelable in Java Code

From Java

How to Call Java Code from MySQL?

From Java

How to call a servlet from Java code

From Dev

How to call ruby code from java (Android)

From Dev

how to call code written in C from assembly?

From Dev

How to call code from SQL in C#

From Dev

How to call input tag to the c# code

From

How do I call a Java Native Interface C function from my Go code?

From Java

How to use collect call in Java 8?

From Java

Call C methods from C++/Java/C# code?

From Dev

How to call c++ methods from JNI

From Dev

How to use QML QtWebView to call C++?

Related Related

HotTag

Archive