【问题标题】:Can I know the name of the class that calls a JNI C method?我能知道调用 JNI C 方法的类的名称吗?
【发布时间】:2012-10-04 03:07:07
【问题描述】:

有什么方法可以知道在 JNI C 代码中调用方法的类的名称?我可以使用以下语句获得对该类的引用:

jclass cls = (*env)->GetObjectClass(env,obj);

但是有什么方法可以让我知道班级的名字吗? .

【问题讨论】:

    标签: java c class java-native-interface


    【解决方案1】:

    就我而言,我还没有获得课程的对象。相反,我想根据其签名获取给定类的名称。

    所以,这对我有用。我希望它可以帮助:

    // Find the class by its JNI signature
    jclass cls = env->FindClass(expectedType);
    
    // Get the class object's class descriptor
    jclass clsClazz = env->GetObjectClass(cls);
    
    // Find the getSimpleName() method in the class object
    jmethodID methodId = env->GetMethodID(clsClazz, "getSimpleName", "()Ljava/lang/String;");
    jstring className = (jstring) env->CallObjectMethod(cls, methodId);
    
    // And finally, don't forget to release the JNI objects after usage!!!!
    env->DeleteLocalRef(clsClazz);
    env->DeleteLocalRef(cls);
    

    【讨论】:

      【解决方案2】:

      此代码将为您提供调用类名称:

      jclass cls = env->GetObjectClass(obj);
      
      // First get the class object
      jmethodID mid = env->GetMethodID(cls, "getClass", "()Ljava/lang/Class;");
      jobject clsObj = env->CallObjectMethod(obj, mid);
      
      // Now get the class object's class descriptor
      cls = env->GetObjectClass(clsObj);
      
      // Find the getName() method on the class object
      mid = env->GetMethodID(cls, "getName", "()Ljava/lang/String;");
      
      // Call the getName() to get a jstring object back
      jstring strObj = (jstring)env->CallObjectMethod(clsObj, mid);
      
      // Now get the c string from the java jstring object
      const char* str = env->GetStringUTFChars(strObj, NULL);
      
      // Print the class name
      printf("\nCalling class is: %s\n", str);
      
      // Release the memory pinned char array
      env->ReleaseStringUTFChars(strObj, str);
      

      请注意,我没有采取任何措施来检查错误。这只是一个描述如何完成的小代码 sn-p。


      您也可以这样做,而不是使用GetStringUTFChars/ReleaseStringUTFChars

      // Make sure that the buffer is large enough
      char str[128];
      jint strlen = env->GetStringUTFLength(strObj);
      env->GetStringUTFRegion(strObj, 0, strlen, str);
      printf("\nCalling class is: %s\n", str);
      

      由于字符串被复制到本地缓冲区,因此无需释放。

      【讨论】:

      • 我认为你不应该使用 strlen 作为变量名,因为这是一个现有的标准 C 函数。
      • 根据我的经验,您实际上并不需要“首先获取类对象”下的步骤; clsObjcls 在功能上是等效的。
      • 如果“按原样”使用,示例代码会严重泄漏本地引用。应删除所有 jobject 和 jclass 引用。此外,这是一个不好的做法: jclass cls = env->GetObjectClass(obj); ... cls = env->GetObjectClass(clsObj);不释放之前存储在 cls 中的引用。
      • @maba,实际上,当您的代码足够大并且进行了大量迭代时,您需要自己删除本地引用。在 JNI 调用期间可以创建多少本地参考是有限制的(仅限 512!)。因此,SergeyCalin 说在他们完成后立即释放它们是一个好习惯是正确的。 (检查以下问题stackoverflow.com/questions/20917777/…stackoverflow.com/questions/47019893/…
      • @LukeHutchison 您需要类描述符来探索类上的方法。您可以在不同的类型上看到类对象的类型为jobject,而类对象描述符的类型为 jclass。
      【解决方案3】:

      只需在 jclass 上调用 getName(),也可以通过 JNI。

      【讨论】:

      • 你的意思是( (*env)->GetObjectClass(env,obj) )->getName()?我想从 jnic 代码中打印类(调用方法)的名称
      • 仅供参考 - 一般来说,当您描述您所做的事情,以及哪些错误消息等阻止您成功时,您会得到更好的帮助。 EJP 的回答是正确的。在不知道您遇到什么错误的情况下,我们无法开始评论什么不起作用。请记住 getName() 将返回一个 jstring...
      • @Y.E.P 不,我不是那个意思。我的意思是我所说的,我说过要“通过 JNI”来做。也就是说,获取getName()的methodID,调用CallObjectMethod...()等
      • @EJP 我无法获取方法 ID。我在尝试获取 methodID 时遇到了异常。异常说,找不到特定的方法。所以我希望类的名称知道当我做jclass cls = (*env)->GetObjectClass(env,obj); 时我获得了谁的类引用,这样当我最终做(*env)->GetMethodID(env,cls,"javaFunction","()V");时我不会得到异常@
      • @Y.E.P 如果您无法获取 Class.getName() 的 methodID,那么您显然做错了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 1970-01-01
      • 1970-01-01
      • 2015-12-01
      • 2016-10-01
      • 1970-01-01
      • 2013-05-25
      相关资源
      最近更新 更多