java jni c 指针_使用有效指针从C调用方法后,Java JNI NullPointerException

TLDR:当我从C调用Java方法时,我正在获得NPE,并且没有明显的原因跳出来.

我在Linux上编写了一些JNI代码来为我调用系统调用轮询(以从连接的设备获取通知).

大部分都运行良好.我的C方法被调用,我从Java获取一个字符串,返回一个指针(作为一个int …我知道,所以起诉我!),并将其成功传递给其他方法.我有很多printfs可以验证这一点.

问题在下面的C方法Java_NativePoller_poll中发生.调用CallVoidMethod的那行似乎可以正常工作,因为随后的printf被调用了,但是我尝试调用的Java方法从未被调用,然后抛出NullPointerException.

这是Java代码:

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);

}

以及相关的C代码:

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)

", 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

", method, objclass);

poller->objclass = objclass;

poller->method = method;

printf("Returning poller %p which has descriptor %d

", 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)

", 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)...

", env, poller->handler, poller->method);

(*env)->ExceptionClear(env);

(*env)->CallVoidMethod(env, poller->handler, poller->method);

if (wasEx(env)) return;

printf("Called.

");

}

}

}

}

JNIEXPORT void JNICALL Java_NativePoller_stopWatching

(JNIEnv* env, jobject nativePoller, jint fileDescriptor) {

struct Poller* poller = (struct Poller*)fileDescriptor;

close(poller->fd.fd);

free(poller);

}

(对不起,代码不是很干净-我还有一些重构工作.)

这是调用它的代码:

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

//...

private void triggerEvent() {

LOG.info("Event triggered!");

}

我所有的printf输出看起来像这样:

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)

这个NPE来自哪里?

谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值