Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

when to use JNIEXPORT and JNICALL in Android NDK?

I'm trying to write my own jni sources. Looking at some ndk samples, I found that they often use those macros JNIEXPORT and JNICALL follewed by the name of java package like this

JNIEXPORT void JNICALL Java_com_example_plasma_PlasmaView_renderPlasma(JNIEnv * env, jobject obj, jobject bitmap, jlong time_ms)

I googled it but I can't understand when and how to use these macros

like image 881
nawara Avatar asked Oct 17 '13 09:10

nawara


People also ask

Why do we need JNI?

JNI provides functions for accessing the contents of array objects. While arrays of objects must be accessed one entry at a time, arrays of primitives can be read and written directly as if they were declared in C.

What is JNIEnv * env?

jint GetVersion(JNIEnv *env); Returns the version of the native method interface.

What is Android NDK used for?

The Native Development Kit (NDK) is a set of tools that allows you to use C and C++ code with Android, and provides platform libraries you can use to manage native activities and access physical device components, such as sensors and touch input.

What is Jclass in JNI?

The jclass instance is your object on which a method will be invoked; you'll need to look up the getName method ID on the Class class, then invoke it on the jclass instance using CallObjectMethod to obtain a jstring result. So in short yes, you just call the getName function and look at the jstring result.


1 Answers

JNIEXPORT and JNICALL are defined in NDK_ROOT/platforms/android-9/arch-arm/usr/include/jni.h. Depending on your setup this path will be different, but mostly similar.

#define JNIIMPORT #define JNIEXPORT  __attribute__ ((visibility ("default"))) #define JNICALL 

JNIEXPORT is used to make native functions appear in the dynamic table of the built binary (*.so file). They can be set to "hidden" or "default" (more info here). If these functions are not in the dynamic table, JNI will not be able to find the functions to call them so the RegisterNatives call will fail at runtime.

It is worth noting that all functions end up in the dynamic table by default, so anyone could decompile your native code quite easily. Every function call is built into the binary just in case JNI needs to find it. This can be changed using the compiler option -fvisibility. I would recommend everyone sets this to -fvisibility=hidden to keep your code secure, and then use JNIEXPORT to flag functions as having external visibility.

Using the strip command just removes the debug symbols, the dynamic table is separate. Have a play with objdump to see how much a person could get out of your .so files.

We recently got tripped up by this, hope this helps someone.

EDIT: We use a custom build system, so the visibility option may be set by default for other build setups. More information is available in this SO answer.

like image 144
Danny Parker Avatar answered Sep 23 '22 01:09

Danny Parker