9

I am very new to JNI and I am trying to figure out how certain things work before I port my C++ iOS code to it. I was successful in getting one of the NDK samples working in Android studio and I can see how Java is able to call C++ functions.

I've been searching around and taking chunks of code, but I haven't been able to get it to work in my specific implementation.

Just to test how things worked I set up a simple text log function in java, and I am trying to call it from my native code but I've run into issues.

Here is my Java function:

public static void log(String s){
        Log.d("Native", s);
}

And C++:

void Log(std::string s){

    JNIEnv *env;
    g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6);

    jstring jstr1 = env->NewStringUTF(s.c_str());

    jclass clazz = env->FindClass("com/android/gl2jni/GL2JNILib");
    jmethodID mid = env->GetStaticMethodID(clazz, "log", "(Ljava/lang/String;)V");

    jobject obj = env->CallStaticObjectMethod(clazz, mid, jstr1);
}

From what I've seen with different examples this should work, but it throws an error:

29835-29849/com.android.gl2jni A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 29849 (Thread-17371)

Am I missing something?

EDIT:

I've changed it to GetStaticMethodID. But after logging the progress of the function I've found out that the line that fails is:

g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6);

Which I figure is because g_JavaVM is set as static JavaVM* g_JavaVM = NULL; and then never touched again. I'm guessing I need to set this variable, but how?

  • You can add __android_log_print(ANDROID_LOG_DEBUG, "myApp", "msg xxx") before each line and find out which one cause SIGSEGV. – Dmitry Sokolov Feb 20 '15 at 07:37
  • I haven't tested the code, but since there is a `GetStaticMethodID` -function in the `JNIEnv` , I would venture a guess that your call to `GetMethodID` cannot find any non-static method matching your signature and then returns null, which you fail to check for. – zenzelezz Feb 20 '15 at 12:25
  • I've changed some code and added some details. –  Feb 20 '15 at 19:25
  • You definitely should initialize g_JavaVM, or pass around the JNIEnv pointer. Every JNI-compliant function receives one as the first parameter. – Seva Alekseyev Feb 20 '15 at 19:28

2 Answers2

11

Part of my problem was that I didn't initialize The JavaVM. The other part was that I was using C++, but I was trying to use the C functions.

The working code is:

Java:

public static void log(String s){
        Log.d("Native", s);
}

C++:

void Log(std::string s){

    JNIEnv *env;
    g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6);

    jstring jstr1 = env->NewStringUTF(s.c_str());

    jclass clazz = env->FindClass("com/android/gl2jni/GL2JNILib");
    jmethodID mid = env->GetStaticMethodID(clazz, "log", "(Ljava/lang/String;)V");

    jobject obj = env->CallStaticObjectMethod(clazz, mid, jstr1);
}

//In some initialization function with Environment variable

env->GetJavaVM(&g_JavaVM);

Hopefully this can help other people with the same problem.

  • 3
    You have a typo, it should be `CallStaticVoidMethod()`. – Pol Oct 02 '15 at 03:06
  • I used javac Foo.java followed by javap -s Foo to get the mangled name. See http://www.rgagnon.com/javadetails/java-0286.html – Glenn Jun 23 '17 at 22:14
1

http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html

GetStaticMethodID

jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);

Returns the method ID for a static method of a class. The method is specified by its name and signature.

18446744073709551615
  • 16,368
  • 4
  • 94
  • 127