Java JNI NullPointerException after calling method from C with valid pointers

tyrel

TLDR: I'm getting a NPE when I call a Java method from C and nothing obvious is jumping out as the cause.

I have written some JNI code on Linux to call the system call poll for me (to get notifications from an attached device).

Most of it is working pretty well; my C methods are getting called, I'm getting a string from Java, returning a pointer (as an int... I know, so sue me!), and successfully passing that to other methods. I've got a lot of printfs to verify this.

The problem is happening in my C method Java_NativePoller_poll below. The line that does CallVoidMethod seems to work, as the printf which follows is called, but the Java method I'm attempting to call never gets called, and a NullPointerException is then thrown.

Here's the Java code:

public class NativePoller {
    public interface NativePollEventHandler {
        void handleEvent();
    }

    /* Opens a file to prepare to poll its status */
    public native int watchFile(String fileName, NativePollEventHandler handler);

    /* Poll a file previously opened */
    public synchronized native void poll(int fd);

    /* Clean up */
    public native void stopWatching(int fd);
}

And the C code in question:

struct Poller {
        struct pollfd fd;
        jobject handler;
        jclass objclass;
        jmethodID method;
};

int wasEx(JNIEnv* env) {
        jthrowable ex = (*env)->ExceptionOccurred(env);
        if (ex) {
                printf("Got an exception!");
                (*env)->ExceptionDescribe(env);
                (*env)->ExceptionClear(env);
                return 1;
        }
        return 0;
}


JNIEXPORT jint JNICALL Java_NativePoller_watchFile
  (JNIEnv* env, jobject nativePoller, jstring fileName, jobject handler) {
        (*env)->ExceptionClear(env);
        const char* file = (*env)->GetStringUTFChars(env, fileName, NULL);
        if (wasEx(env)) return -1;
        int fd = open(file, O_RDONLY);
        if (fd < 0) {
                fprintf(stderr, "Failed to open %s for reading (errno=%d)\n", file, errno);
                (*env)->ReleaseStringUTFChars(env, fileName, file);
                if (wasEx(env)) return -1;
                return fd;
        }

        (*env)->ReleaseStringUTFChars(env, fileName, file);
        if (wasEx(env)) return -1;

        struct Poller* poller = malloc(sizeof(struct Poller));
        poller->fd.fd = fd;
        poller->fd.events = POLLIN;
        poller->handler = handler;
        jclass objclass = (*env)->GetObjectClass(env, handler);
        if (wasEx(env)) return -1;
        jmethodID method = (*env)->GetMethodID(env, objclass, "handleEvent", "()V");
        if (wasEx(env)) return -1;

        printf("Found method %p in class %p\n", method, objclass);

        poller->objclass = objclass;
        poller->method = method;

        printf("Returning poller %p which has descriptor %d\n", poller, poller->fd.fd);

        return (int)poller;
}

JNIEXPORT void JNICALL Java_NativePoller_poll
  (JNIEnv* env, jobject nativePoller, jint pollerAddress) {
        struct Poller* poller = (struct Poller*)pollerAddress;
        printf("Polling for %p (%d)\n", poller, poller->fd.fd);
        int ret = poll(&poller->fd, 1, 1);
        if (ret > 0) {
                printf("Got something! Events is %08X", poller->fd.events);
                if (poller->fd.events & POLLIN) {
                        if (poller->method != 0) {
                                printf("Calling: CallVoidMethod(%p, %p, %p)...\n", env, poller->handler, poller->method);
                                (*env)->ExceptionClear(env);
                                (*env)->CallVoidMethod(env, poller->handler, poller->method);
                                if (wasEx(env)) return;
                                printf("Called.\n");
                        }
                }
        }
}

JNIEXPORT void JNICALL Java_NativePoller_stopWatching
  (JNIEnv* env, jobject nativePoller, jint fileDescriptor) {
        struct Poller* poller = (struct Poller*)fileDescriptor;
        close(poller->fd.fd);
        free(poller);
}

(Sorry the code isn't super clean -- I still have a bit of refactoring to do.)

Here's the code that's calling it:

watchFd = nativePoller.watchFile(ROOT_PATH + pinPath + "value", this::triggerEvent);

//...

private void triggerEvent() {
    LOG.info("Event triggered!");
}

All my printf output looks like this:

Found method 0x63d03b48 in class 0x63d02860
Returning poller 0x63d036a8 which has descriptor 18
Polling for 0x63d036a8 (18)
Got something! Events is 00000001
Calling: CallVoidMethod(0x63d03d3c, 0x630d0aa8, 0x63d03b48)...
Got an exception!
Exception in thread "Thread-12" java.lang.NullPointerException
        at my.package.NativePoller.poll(Native Method)
        at my.package.GPIOPinImpl.run(GPIOPinImpl.java:116)
        at java.lang.Thread.run(Thread.java:745)

Where's this NPE coming from?

Thanks!

apangin

You are reusing jobject handler and jclass objclass across method calls. This is illegal unless the references are made global.

See this answer for details.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Java

Calling a java method from c++ in Android

From Java

Passing pointers between C and Java through JNI

From Java

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

From Java

JNI: From C code to Java and JNI

From Java

I am getting java.lang.NullPointerException on Jenkisn while calling method from groovy script

From Java

NullPointerException when calling method from another class

From

Are pointers considered a method of calling by reference in C?

From Dev

Calling a static void Java method from JNI

From Dev

Calling dll implemented JNI from C++

From Dev

JNI Calling Java Method With Array Parameter

From Dev

Calling C function with pointers from F#

From Dev

Mockito : java.lang.NullPointerException when calling method from mocked Class

From Dev

JNI calling Java from C++ with multiple threads

From Dev

Calling C system calls from JNI

From Dev

NullPointerException when calling a method from a different class

From Dev

NullPointerException while calling a method from service

From Dev

Java Program terminates after JNI method call

From Dev

JNI C++ UnsatisfiedLinkError When Calling Method

From Dev

Calling a Java Method from the native code using jni

From Dev

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

From Dev

NullPointerException when calling a Fragment method from Activity?

From Dev

Calling a C library method from swift using pointers

From Dev

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

From Dev

Stopping the method from calling :after

From Dev

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

From Dev

Calling C function from Fortran with pointers

From Dev

Calling RenderScript from C / JNI

From Dev

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

From Dev

Calling JAVA Method from XQuery

Related Related

  1. 1

    Calling a java method from c++ in Android

  2. 2

    Passing pointers between C and Java through JNI

  3. 3

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

  4. 4

    JNI: From C code to Java and JNI

  5. 5

    I am getting java.lang.NullPointerException on Jenkisn while calling method from groovy script

  6. 6

    NullPointerException when calling method from another class

  7. 7

    Are pointers considered a method of calling by reference in C?

  8. 8

    Calling a static void Java method from JNI

  9. 9

    Calling dll implemented JNI from C++

  10. 10

    JNI Calling Java Method With Array Parameter

  11. 11

    Calling C function with pointers from F#

  12. 12

    Mockito : java.lang.NullPointerException when calling method from mocked Class

  13. 13

    JNI calling Java from C++ with multiple threads

  14. 14

    Calling C system calls from JNI

  15. 15

    NullPointerException when calling a method from a different class

  16. 16

    NullPointerException while calling a method from service

  17. 17

    Java Program terminates after JNI method call

  18. 18

    JNI C++ UnsatisfiedLinkError When Calling Method

  19. 19

    Calling a Java Method from the native code using jni

  20. 20

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

  21. 21

    NullPointerException when calling a Fragment method from Activity?

  22. 22

    Calling a C library method from swift using pointers

  23. 23

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

  24. 24

    Stopping the method from calling :after

  25. 25

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

  26. 26

    Calling C function from Fortran with pointers

  27. 27

    Calling RenderScript from C / JNI

  28. 28

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

  29. 29

    Calling JAVA Method from XQuery

HotTag

Archive