1

当为我的 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!");
        }
    };

我的日志猫:

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;
}
4

2 回答 2

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

您正在JNIEnv线程之间共享一个。不要那样做——JNIEnv是线程特定的。

要么使用传入的作为从 Java 代码调用的本机方法的第一个参数,要么将 保存JavaVM在全局中并通过JNIEnvGetEnv调用获取。

另请参阅JNI 提示页面。

于 2013-08-20T19:28:17.317 回答
2

如果你想使用JNIEnv,你必须AttachCurrentThread()在你的线程中调用以将自己附加到 VM 并获取一个 JNI 接口指针。这是Oracle 的 JNI 参考

于 2013-08-21T01:17:49.773 回答