JNI将String转换为char *,由实例方法

时间:2016-05-27 21:59:01

标签: java c java-native-interface

在我的程序C中从Java调用,C函数可以在Java上下文之外调用,但有时需要一些Java资源。我应该解释一下程序是什么......所以C库是一个可以加载C插件的插件系统,插件有时需要访问Java资源,例如检索String id。

因此,当加载插件系统时,JNI会调用init函数,因此可以存储JNIEnv *jobject以供插件进一步访问。

在java类中我提供了访问这些资源的实例方法,例如我有方法

private String getId() {
  return "Bryan";
}

C插件系统有一个功能

char *get_id(char *id) {
  jobject jobj = (*jvm.env)->CallObjectMethod(jvm.env, jvm.this, jvm.getId);
  jstring jid = jobj;
  if (jid == NULL) 
    debug("get_id", RED "jid NULL");
   else 
     debug("get_id", RED "jid not null"); */
  debug("get_id", RED "in get_id, method called");
  const char *cid = (*jvm.env)->GetStringUTFChars(jvm.env, jid, NULL);
  debug("get_id", RED "converted to c string: %s", cid);
  strcpy(id, cid);
  debug("get_id", RED "string copied");
  (*jvm.env)->ReleaseStringUTFChars(jvm.env, jid, cid);
  debug("get_id", RED "string released");
  return id;
}

其中jvm是一个结构,其中包含与初始化时存储的envobj对应的字段JNIEnv *jobject,以及jvm.getId {同时初始化methodID Java实例方法的{1}}。 调试宏只是调用getId printf来帮助我调试程序。

这是调用flush之后的输出:

get_id

正如您所看到的,对DEBUG IN plugin_system.c LINE 339: In get_id in get_id, calling method... DEBUG IN plugin_system.c LINE 343: In get_id jid NULL DEBUG IN plugin_system.c LINE 346: In get_id in get_id, method called # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007fb6bcb6cd70, pid=25254, tid=0x00007fb6974be700 # # JRE version: OpenJDK Runtime Environment (8.0_92-b14) (build 1.8.0_92-b14) # Java VM: OpenJDK 64-Bit Server VM (25.92-b14 mixed mode linux-amd64 compressed oops) # Problematic frame: # V [libjvm.so+0x675d70] # # Core dump written. Default location: /home/kowa/code/reseaux/projet/ringo/java/bin/core or core.25254 # # An error report file with more information is saved as: # /home/kowa/code/reseaux/projet/ringo/java/bin/hs_err_pid25254.log # # If you would like to submit a bug report, please visit: # http://bugreport.java.com/bugreport/crash.jsp # The crash happened outside the Java Virtual Machine in native code. # See problematic frame for where to report the bug. # [4] 25254 abort (core dumped) java Jring Nick 9999 8888 1 的调用是(看起来)成功,但核心转储是由getId触发的。

出了什么问题?

1 个答案:

答案 0 :(得分:1)

您无法缓存JVM' env。请参阅Keeping a global reference to the JNIEnv environment,尤其是this answer

  

JNI接口指针(JNIEnv)仅在当前有效   线。如果另一个线程需要访问Java VM,它必须   首先调用AttachCurrentThread()将自身附加到VM并获取   一个JNI接口指针。一旦附加到VM,就是本机线程   就像在本机中运行的普通Java线程一样工作   方法。本机线程保持连接到VM,直到它调用   DetachCurrentThread()分离自己。

Updated link。另一个答案中的链接是陈旧的。

就Java对象,类和方法ID而言,如果您要对它们进行缓存,则需要obtain a global reference。请参阅What is 'JNI Global reference'Caching JNI objects and thread-safety (in Android)