当CallVoidMethod到java函数处理时JNI崩溃

时间:2013-08-20 18:19:40

标签: android android-ndk java-native-interface

当我的UDP程序调用我的JNI函数CallVoidMethod时,我的程序崩溃了。我无法从logcat解密问题。任何帮助将不胜感激。

我的代码片段:

JNI功能:

jmethodID constructID, methodID;
JNIEnv* env;
jclass clazz;
JavaVM *g_jm;
int downLoad_speed_test_start(JNIEnv * envl, jobject thiz, int serverport) {
        jobject obj;


    struct sockaddr_in servAddr, clientAddr;
    int slen = sizeof(clientAddr);
    char buf[512];
    int socket_ovdp;
    if ((socket_ovdp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
        __android_log_print(ANDROID_LOG_DEBUG, "MY_TAG",
                "\nSocket() unsuccessful\n");
    else
        __android_log_print(ANDROID_LOG_DEBUG, "MY_TAG",
                "\nServer: Socket() successful\n");

    bzero(&servAddr, sizeof(servAddr));

    servAddr.sin_family = AF_INET;
    servAddr.sin_port = htons(serverport);
    inet_addr("127.0.0.1");
        clazz=env->GetObjectClass(thiz);
        constructID = env->GetMethodID(clazz, "<init>","()V");
        methodID = env->GetMethodID(clazz,"jniCall","(I)V");
        obj=env->NewObject(clazz,constructID);
        JavaVM *jm;
        env->GetJavaVM(&jm);

    if (bind(socket_ovdp, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1)
        __android_log_print(ANDROID_LOG_DEBUG, "MY_TAG",
                "\nServer : bind() failed!\n");

    else
    {
        __android_log_print(ANDROID_LOG_DEBUG, "MY_TAG",
                "\nServer : bind() successful\n");
    }

    while (true) {
        if (recvfrom(socket_ovdp, buf, 512, 0, (struct sockaddr*) &clientAddr,
                &slen) == -1)
            __android_log_print(ANDROID_LOG_DEBUG, "MY_TAG",
                    "\nRecvfrom() did not work\n");
        else
        {
        //handle message
        __android_log_print(ANDROID_LOG_DEBUG, "MY_TAG", "\nReceived: %s\n\n",
                buf);
            int newbuf = 5;
            env->CallVoidMethod(obj,methodID,newbuf);
        }
    }

    return 0;

}

处理程序的Java函数:

void jniCall(int arg)
    {

        Message m = mHandler.obtainMessage();
        m.arg1=arg;
        mHandler.sendMessageDelayed(m, 10/* ms */);
        }

public Handler mHandler = new Handler(Looper.getMainLooper()){
        @Override
        public void handleMessage(Message msg){
            try{
                chatbox.setText("Got it!");
            }catch(Exception e){
                Log.i("MYLOG", "Message was not handled.");
            }
            //chatbox.setText(chatbox.getText() + "Got it!");
        }
    };

我的logcat:

08-20 18:09:26.200: W/dalvikvm(3521): JNI WARNING: threadid=15 using env from threadid=16
08-20 18:09:26.200: W/dalvikvm(3521):              in Lcom/WifiSpeedTest2/WifiSpeedTestActivity;.ovt_downLoad_speed_test_start:(I)I (CallVoidMethodV)
08-20 18:09:26.210: I/dalvikvm(3521): "Thread-154" prio=5 tid=15 NATIVE
08-20 18:09:26.210: I/dalvikvm(3521):   | group="main" sCount=0 dsCount=0 obj=0x40d332f8 self=0x2a1b96f0
08-20 18:09:26.221: I/dalvikvm(3521):   | sysTid=3555 nice=0 sched=0/0 cgrp=apps handle=706079760
08-20 18:09:26.221: I/dalvikvm(3521):   | state=R schedstat=( 7136784 37413210 12 ) utm=0 stm=0 core=0
08-20 18:09:26.250: I/Thread:(3521): connected lost
08-20 18:09:26.380: I/dalvikvm(3521):   #00  pc 000012a0  /system/lib/libcorkscrew.so (unwind_backtrace_thread+27)
08-20 18:09:26.411: I/dalvikvm(3521):   #01  pc 0005faa8  /system/lib/libdvm.so (dvmDumpNativeStack(DebugOutputTarget const*, int)+35)
08-20 18:09:26.411: I/dalvikvm(3521):   #02  pc 00053914  /system/lib/libdvm.so (dvmDumpThreadEx(DebugOutputTarget const*, Thread*, bool)+303)
08-20 18:09:26.420: I/dalvikvm(3521):   #03  pc 000539ae  /system/lib/libdvm.so (dvmDumpThread(Thread*, bool)+25)
08-20 18:09:26.420: I/dalvikvm(3521):   #04  pc 00038aba  /system/lib/libdvm.so
08-20 18:09:26.430: I/dalvikvm(3521):   #05  pc 0003fc24  /system/lib/libdvm.so
08-20 18:09:26.430: I/dalvikvm(3521):   #06  pc 0000150c  /data/app-lib/com.WifiSpeedTest2-2/libwifiSpeedTest2.so (_JNIEnv::CallVoidMethod(_jobject*, _jmethodID*, ...)+60)
08-20 18:09:26.430: I/dalvikvm(3521):   #07  pc 00001c18  /data/app-lib/com.WifiSpeedTest2-2/libwifiSpeedTest2.so (ovt_downLoad_speed_test_start(_JNIEnv*, _jobject*, int)+956)
08-20 18:09:26.430: I/dalvikvm(3521):   #08  pc 00001e64  /data/app-lib/com.WifiSpeedTest2-2/libwifiSpeedTest2.so (ovt_downLoad_speed_test_start_jni(_JNIEnv*, _jobject*, int)+72)
08-20 18:09:26.441: I/dalvikvm(3521):   #09  pc 0001e290  /system/lib/libdvm.so (dvmPlatformInvoke+112)
08-20 18:09:26.470: I/dalvikvm(3521):   #10  pc 0004d1f8  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+391)
08-20 18:09:26.470: I/dalvikvm(3521):   #11  pc 00038b44  /system/lib/libdvm.so (dvmCheckCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+7)
08-20 18:09:26.470: I/dalvikvm(3521):   #12  pc 000276a0  /system/lib/libdvm.so
08-20 18:09:26.470: I/dalvikvm(3521):   #13  pc 0002b540  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
08-20 18:09:26.470: I/dalvikvm(3521):   #14  pc 0005f9d4  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+271)
08-20 18:09:26.470: I/dalvikvm(3521):   #15  pc 0005f9fe  /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...)+19)
08-20 18:09:26.470: I/dalvikvm(3521):   #16  pc 00054576  /system/lib/libdvm.so
08-20 18:09:26.481: I/dalvikvm(3521):   #17  pc 0000e3b8  /system/lib/libc.so (__thread_entry+72)
08-20 18:09:26.481: I/dalvikvm(3521):   #18  pc 0000dab0  /system/lib/libc.so (pthread_create+160)
08-20 18:09:26.481: I/dalvikvm(3521):   at com.WifiSpeedTest2.WifiSpeedTestActivity.ovt_downLoad_speed_test_start(Native Method)
08-20 18:09:26.491: I/dalvikvm(3521):   at com.WifiSpeedTest2.WifiSpeedTestActivity$receiveVideoThread.run(WifiSpeedTestActivity.java:96)
08-20 18:09:26.500: E/dalvikvm(3521): VM aborting
08-20 18:09:26.500: A/libc(3521): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 3555 (Thread-154)

编辑:添加OnLoad和其他功能

int downLoad_speed_test_start_jni(JNIEnv * envl, jobject thiz,
        int serverport) {

    env = envl;
    //env->GetJavaVM(&g_jm);
    downLoad_speed_test_start(env, thiz, serverport);
}


jint JNI_OnLoad(JavaVM* vm, void* reserved)

{

    jint result = -1;
    g_jm = vm;

    // catched_jvm = vm;
    LOGE("JNI_OnLoad\n");
    static const char* const strClassName =
            "com/WifiSpeedTest2/WifiSpeedTestActivity";
    //static const char* const strClassName = "com/MultPkg/Mult";

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {

        LOGE("ERROR: GetEnv failed\n");

        return result;

    }

    if (env == NULL) {

        LOGE("ERROR: env is NULL\n");

        return result;

    }

    /* find the class handle */

    clazz = env->FindClass(strClassName);

    if (clazz == NULL) {

        LOGE("Can't find class %s\n", strClassName);

        return result;

    }

    // fields.clazz = (jclass) env->NewGlobalRef(clazz);

    /* register all the methods */

    if (env->RegisterNatives(clazz, gMethods,
            sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)

    {

        LOGE("Failed registering methods for %s\n", strClassName);

        return result;

    }

    /* success -- return valid version number */

    result = JNI_VERSION_1_4;
    __android_log_print(ANDROID_LOG_DEBUG, "MY_TAG",
                        "\nJNI OnLoad worked.\n");
    return result;
}

2 个答案:

答案 0 :(得分:6)

JNI WARNING: threadid=15 using env from threadid=16

您在线程之间共享JNIEnv。不要这样做 - JNIEnv是特定于线程的。

使用传入的内容作为从Java代码调用的本机方法的第一个参数,或者在全局中保存JavaVM并使用GetEnv call获取JNIEnv

另请参阅JNI Tips页面。

答案 1 :(得分:2)

如果您想使用JNIEnv,则必须在线程中调用AttachCurrentThread()以将自身附加到VM并获取JNI接口指针。这是Oracle's JNI reference