当前位置: 首页 > 知识库问答 >
问题:

JNI将字符串转换为char*,由实例方法返回

慕容嘉熙
2023-03-14

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

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

在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*jject,以及jvm.getId,它是同时iniziated的getIdJava实例方法的方法ID。调试宏只是用flush调用printf来帮助我调试程序。

这是调用get\u 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

如您所见,对JavagetId的调用(看起来)是成功的,但是由GetStringUTFChars触发了核心转储。

怎么了?

共有1个答案

文心思
2023-03-14

您无法缓存JVM的env。请参阅保留对JNIEnv环境的全局引用,尤其是这个答案:

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

更新链接。另一个答案中的链接已过时。

至于Java对象、类和方法id,如果要缓存它们,则需要获得对它们的全局引用。查看什么是“JNI全局引用”,缓存JNI对象和线程安全(在Android中)

 类似资料:
  • 问题内容: 我已经通过使用JNI 将URL字符串从Java传递为C代码作为数据类型。我的库方法需要一个as url。 我如何转换的? PS:在C中使用jcharArray有什么优势吗?(即在本地方法中传递而不是字符串) 问题答案: 这是我开始使用JNI时发现的几个有用的链接 http://en.wikipedia.org/wiki/Java_Native_Interface http://down

  • 问题内容: 是否存在将“ \ uFFFF”之类的字符串转换为字符的标准方法,即六个字符的字符串包含一个Unicode字符的表示形式? 问题答案: 该值直接解释为所需的字符串,整个序列实现为单个字符。 换句话说,如果要对值进行硬编码: 请注意,这似乎不是适当的Unicode字符,但请尝试使用例如。 在此处阅读有关Unicode转义的信息

  • 问题内容: 我试图将const char *传递给从Swift中的Swift字符串转换而来的旧C库。 这是我正在调用的C函数: 如何将Swift字符串转换为这种const char类型?当我像这样传递ipAddress时,它可以工作: 但是当我这样通过时dit不起作用 我在需要指定类型的函数中需要它: 我尝试使用AnyObject而不是String,但这也不起作用。 谢谢。 问题答案: 不知道为什

  • 问题内容: 我正在编写一个将数据存储在字典对象中的程序,但是该数据需要在程序执行过程中的某个时候保存,并在再次运行该程序时重新加载到字典对象中。我如何将字典对象转换为可以写入文件并再加载回字典对象的字符串?希望这将支持包含词典的词典。 问题答案: json模块是一个很好的解决方案。与pickle相比,它的优势在于它仅生成纯文本输出,并且是跨平台和跨版本的。

  • 问题内容: 如何将经典字符串转换为f字符串? 输出: 所需的输出: 问题答案: f字符串是 语法 ,而不是对象类型。您不能将任意字符串转换为该语法,该语法会创建一个字符串对象,而不是相反。 我假设您想用作模板,因此只需在对象上使用方法: 如果要提供可配置的模板服务,请创建一个包含所有可以插值的字段的名称空间字典,并与调用语法一起使用以应用名称空间: 然后,用户可以在字段中的名称空间中使用任何键(或

  • 问题内容: 我正在寻找一种将包含字符转义序列的字符串转换为表示的字符的方法。 因此,例如,我想将字符串(具有两个字符,一个反斜杠和一个双引号)解析为char 。因此,将一个字符数组转换为一个字符。 因此,可能会执行以下操作,反之亦然: 我不敢相信java.lang或其他任何东西都不能为此提供良好的代码(也许是本地代码),因为我觉得上面的代码可能不完整,并且无法解析每个有问题的(可逃避的?)字符,因