zoukankan      html  css  js  c++  java
  • JNI:在线程或信号处理函数中访问自定义类

    在写一个Tomcat应用,类需要被信号处理函数回调,可是在单独的程序中测试没用问题:
    void OnSingalHandler(int sig)
    {
      ...
      JNIEnv* env=NULL;	
      if (g_VM->AttachCurrentThread((void**)&env, NULL) != JNI_OK)
      {
    	printf("AttachCurrentThread failed!
    ");            
      }   	
     
      jclass cls = env->FindClass("nms/scada/Rtdb");
      jmethodID callback = env->GetStaticMethodID(cls,"RealDataChange","(Ljava/lang/String;)V"); 								
      env->CallStaticVoidMethod(cls,callback,CStr2Jstring(env,xmlDoc.GetDoc().c_str())); 
      
      g_VM->DetachCurrentThread();
    
      ...
    
    }

        一切安好,可是移到Tomcat中时,FindClass就不工作了,无论如何返回都是NULL,看网上说是因为Tomcat的ClassLoader不一样了,种种,试了好久未果。

        后来发现即使是在Tomcat中,在JNI_OnLoad函数依然可以用FindClass调用成功,唯独在线程或者信号处理函数中有问题,或许是和AttachCurrentThread有关系吧。

        于是想用全局变量缓存JNI_OnLoad中FindClass的结果,结果失败。

    后来又有人说全局变量缓存是可以用的,不过要用NewGlobalRef创建全局对象引用,查了一下NewGlobalRef的定义:

       jobject NewGlobalRef(jobject obj);

    根本就没有给jclass用的啊,于是又开始乱找原因,试着用Tomcat的ClassLoader什么的原因。最终也没有成功。

    又不甘心,查看jobject和jclass尼玛,原来是一回事

         typedef jobject jclass;

    好了,一用,妥妥的成功了。

    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
    {
        ...
        jclass classClass = env->FindClass("nms/scada/Rtdb");
        g_Class = (jclass)env->NewGlobalRef((jobject)classClass);
        ...
    }

      完。

  • 相关阅读:
    ubuntu
    ubuntu
    ubuntu14.04,安装Gnome 15.10 (桌面)
    ubuntu14.04,安装Gnome 15.10 (桌面)
    Ubuntu 14.04.3 LTS如何安装谷歌输入法
    Ubuntu 14.04.3 LTS如何安装谷歌输入法
    ubuntu 安装 删除 卸载 Deb 包文件
    失去爆破音规律
    单词发音规律
    英式音标和美式音标的差异
  • 原文地址:https://www.cnblogs.com/jans2002/p/4673101.html
Copyright © 2011-2022 走看看