JNI: Calling a java method from C periodically is not working

Autumn

I am calling a java method from JNI layer periodically (every 50ms) using timer_create. My Java method ( callback() ) gets called for sometime but after that its not getting called and my application hangs. If I touch anything on the screen I get ANR.

To check whether it's a timer issue or JNI call (calling java method), I commented everything inside handler() except log statement. I observed that log is getting printed continuously, which made me conclude that problem is in calling java method from handler().

I am not sure on which thread(UI or non-UI) this JNI call is made when I use AttachCurrentThread() . If its made on UI thread then please let me know how to make it run on non-UI thread. Or is there any other problem in my code which is causing it.

If you observe the output, native and java methods are called continuously but after sometime only native method is called and after few calls that too gets stopped.

/******************Native Code**************************/

void handler(int sig, siginfo_t *si, void *uc) {
    JNIEnv * g_env;

    __android_log_print(ANDROID_LOG_INFO, TAG, "Native handler"); 

    int getEnvStat = (*g_vm)->GetEnv(g_vm,(void **)&g_env, JNI_VERSION_1_6);

    if (getEnvStat == JNI_EDETACHED) {

        if ((*g_vm)->AttachCurrentThread(g_vm, (void **) &g_env, NULL) != 0) {

        }
    } else if (getEnvStat == JNI_OK) {

    } else if (getEnvStat == JNI_EVERSION) {

    }

    (*g_env)->CallVoidMethod(g_env,g_obj, g_mid);

    if ((*g_env)->ExceptionCheck(g_env)) {
        (*g_env)->ExceptionDescribe(g_env);
    }
}

void initTimer() {

    struct new_value;
    struct sigaction action;
    struct sigevent sev;
    timer_t timerid;

    /* Establish handler for timer signal */
    action.sa_flags = SA_SIGINFO;
    action.sa_sigaction = handler;
    sigemptyset(&action.sa_mask);
    if (sigaction(SIG1, &action, NULL) == -1)
        __android_log_print(ANDROID_LOG_INFO, TAG, "sigaction");

    /* Create the timer */
    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIG1;
    sev.sigev_value.sival_ptr = &timerid;
    if (timer_create(CLOCK_MONOTONIC, &sev, &timerid) == -1)
        __android_log_print(ANDROID_LOG_INFO, TAG, "timer_create");

    /* Start the timer */
    new_value.it_interval.tv_sec = 0;
    new_value.it_interval.tv_nsec = 50*1000000; /* 50 ms*/
    new_value.it_value.tv_sec = 0;
    new_value.it_value.tv_nsec = 50*1000000; /* 50 ms */
    if (timer_settime(timerid, 0, &new_value, NULL) == -1)
        __android_log_print(ANDROID_LOG_INFO, TAG, "timer_settime");
}

JNIEXPORT void JNICALL Java_com_foo_MyJavaClass_register
        (JNIEnv * env, jobject obj, jint delay) {


    // convert local to global reference
    // local will die after this method call
    g_obj = (*env)->NewGlobalRef(env, obj);

    // save refs for callback
    jclass g_clazz = (*env)->GetObjectClass(env, g_obj);
    if (g_clazz == NULL) {

    }

    g_mid = (*env)->GetMethodID(env, g_clazz, "callback", "()V");
    if (g_mid == NULL) {

    }

    initTimer();

}

/***Java callback **/

public class MyJavaClass {

    public void callback() {

        Log.e("", "Java callback " );

    }

    public native void register(int delayInMs);

}

/***Output log****/

09-06 05:00:45.430: I/(31763): Native handler
09-06 05:00:45.430: E/(31763): Java callback : : : 09-06 05:00:45.480: I/(31763): Native handler
09-06 05:00:45.480: E/(31763): Java callback 09-06 05:00:45.520: I/(31763): Native handler
09-06 05:00:45.520: E/(31763): Java callback 09-06 05:00:45.570: I/(31763): Native handler
09-06 05:00:45.570: E/(31763): Java callback 09-06 05:00:45.620: I/(31763): Native handler
09-06 05:00:45.620: E/(31763): Java callback 09-06 05:00:45.680: I/(31763): Native handler
09-06 05:00:45.680: E/(31763): Java callback 09-06 05:00:45.720: I/(31763): Native handler
09-06 05:00:45.770: I/(31763): Native handler
09-06 05:00:45.840: I/(31763): Native handler
09-06 05:00:45.880: I/(31763): Native handler
09-06 05:00:45.930: I/(31763): Native handler 09-06 05:00:45.970: I/(31763): Native handler
09-06 05:00:46.030: I/(31763): Native handler
09-06 05:00:46.070: I/(31763): Native handler
09-06 05:00:46.130: I/(31763): Native handler
09-06 05:00:46.180: I/(31763): Native handler
09-06 05:00:46.230: I/(31763): Native handler
09-06 05:00:46.270: I/(31763): Native handler
09-06 05:00:46.330: I/(31763): Native handler
09-06 05:00:46.370: I/(31763): Native handler

Any idea on how to resolve this issue? Thanks in advance !

Zaboj Campula

Andrew's comment is correct. It is a bad idea to call JVM from a signal handler. There is no control what the JVM does and signal handler must be async-signal-safe. So what to do? There are 2 options in general:

Option 1

Use SIGEV_THREAD instead of SIGEV_SIGNAL`. Each timer tick creates a new thread and executes it. It might be a performance bottleneck for fast timers.

struct sigevent sev;
timer_t timerid;
memset(&sev, 0, sizeof(sev));
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = handler;
sev.sigev_value.sival_ptr = &timerid;
timer_create(CLOCK_MONOTONIC, &sev, &timerid);

The timer handler is running always in a new thread so the handler must always attach and detach JVM.

Option 2

Change the design of your application. Start a new native thread that will wait for a flag in an infinite loop. The flag can be set inside the signal handler. When the flag is set then the native thread wakes up and call JNI, and then start waiting for another flag set. You can use a semaphore to implement the flag. Note the sem_post is async-signal-safe.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Java JNI NullPointerException after calling method from C with valid pointers

From Dev

Calling a static void Java method from JNI

From Dev

Calling java function from c++ using jni: Failed to find static method id

From Dev

Calling a Java Method from the native code using jni

From Dev

Calling a method from superclass not working Java

From Dev

Calling RenderScript from C / JNI

From Dev

JNI calling Java from C++ with multiple threads

From Java

Calling a java method from c++ in Android

From Dev

JNI Calling Java Method With Array Parameter

From Dev

JNI C++ UnsatisfiedLinkError When Calling Method

From Dev

Calling C++ Method from Python using ctypes not working

From Dev

How to resolve a Bad global or local ref passed to JNI error when calling a java method from native code

From Java

Android ndk : Problem for call of Java method from c++ with jni

From Dev

Calling dll implemented JNI from C++

From Dev

Calling C system calls from JNI

From Dev

Error while calling C# from java using jni4net from 64 bit Os

From Dev

Calling JAVA Method from XQuery

From Java

JNI: From C code to Java and JNI

From Java

Android: Calling java method with byte[] parameter from c++

From Dev

Calling a method from within itself is not working

From Dev

Calling a method from ABL code not working

From Java

Calling a Method from Constructor Method - Java

From Java

calling another method from the main method in java

From Dev

Call Java Enum method from JNI

From Dev

C# - Refresh method periodically

From Dev

C++ Multithread Java JNI method Call

From Dev

Calling Java Methods from JNI results in program crash

From Java

Calling into a saved java object via JNI from a different thread

From Dev

JNI vs JNA, calling Java from Fortran95

Related Related

  1. 1

    Java JNI NullPointerException after calling method from C with valid pointers

  2. 2

    Calling a static void Java method from JNI

  3. 3

    Calling java function from c++ using jni: Failed to find static method id

  4. 4

    Calling a Java Method from the native code using jni

  5. 5

    Calling a method from superclass not working Java

  6. 6

    Calling RenderScript from C / JNI

  7. 7

    JNI calling Java from C++ with multiple threads

  8. 8

    Calling a java method from c++ in Android

  9. 9

    JNI Calling Java Method With Array Parameter

  10. 10

    JNI C++ UnsatisfiedLinkError When Calling Method

  11. 11

    Calling C++ Method from Python using ctypes not working

  12. 12

    How to resolve a Bad global or local ref passed to JNI error when calling a java method from native code

  13. 13

    Android ndk : Problem for call of Java method from c++ with jni

  14. 14

    Calling dll implemented JNI from C++

  15. 15

    Calling C system calls from JNI

  16. 16

    Error while calling C# from java using jni4net from 64 bit Os

  17. 17

    Calling JAVA Method from XQuery

  18. 18

    JNI: From C code to Java and JNI

  19. 19

    Android: Calling java method with byte[] parameter from c++

  20. 20

    Calling a method from within itself is not working

  21. 21

    Calling a method from ABL code not working

  22. 22

    Calling a Method from Constructor Method - Java

  23. 23

    calling another method from the main method in java

  24. 24

    Call Java Enum method from JNI

  25. 25

    C# - Refresh method periodically

  26. 26

    C++ Multithread Java JNI method Call

  27. 27

    Calling Java Methods from JNI results in program crash

  28. 28

    Calling into a saved java object via JNI from a different thread

  29. 29

    JNI vs JNA, calling Java from Fortran95

HotTag

Archive