【发布时间】:2016-05-27 21:59:01
【问题描述】:
在我的程序中,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是一个结构体,其中包含env和obj字段,对应于初始化时存储的JNIEnv *和jobject,jvm.getId是getIdJava实例方法的methodID同时初始化。
调试宏只是调用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
如您所见,对 Java getId 的调用(看起来)是成功的,但核心转储是由 GetStringUTFChars 触发的。
怎么了?
【问题讨论】:
-
您的
jvm对象是什么?结构?一类?你怎么填写?通常,您不能缓存诸如 JVMenv值之类的值。除非您创建 global reference,否则您也不能缓存对象或方法 ID。 -
这是一个
struct jvm { JNIEnv * env; jobject this; jclass thisClass; methodID getId; };,该字段是在加载库后,在java调用本机init函数后填充的。 -
首先,您对 C 字符串使用的字符集和编码是系统默认的还是特定的?
标签: java c java-native-interface