我有一个调用main
c 本机代码中的函数的线程。
这不会返回到 java,所以我必须小心内存分配。
main 函数调用 java 上的静态方法作为回调的一种方式。以下是在 c 中如何实现的:
void writeat(int x, int y, int style, char *string) {
JNIEnv *env = getJNIEnv();
static jmethodID cls_mid = NULL;
if (cls_mid == NULL) {
jclass clazz = (*env)->FindClass(env, "com/comp/prod/Kernel");
cls_mid = (*env)->GetStaticMethodID(env, clazz, "writeat",
"(IIILjava/lang/String;)V");
}
{
jstring out = (*env)->NewStringUTF(env, string);
(*env)->CallStaticVoidMethod(env, nullVoid, cls_mid, x, y, style,
out);
(*env)->DeleteLocalRef(env, out);
}
}
这工作了一小会儿,然后死了,没有任何错误记录在 log cat 中。
如果我注释掉这个CallStaticVoidMethod
电话,它仍然会做同样的事情。如果我注释掉新调用和删除调用,则没有问题。
仅使用字符串“000”就可以每秒调用数百次,这就是我认为它很快耗尽内存的原因。
获取有关诊断错误的信息的任何帮助都会很棒,因为此时我在日志猫中什么也看不到。
更新:我的旧 main 和 getJNIEnv
JNIEnv *_env;
JNIEXPORT void JNICALL Java_com_comp_prod_main(JNIEnv *env,
jclass thiz) {
LOGV("Main called %d", __LINE__);
_env = (JNIEnv *) ((*env)->NewGlobalRef(env, env));
main();
_env = NULL;
}
JNIEnv *getJNIEnv(void) {
return _env;
}
我的新 main 和 getJNIEnv
JavaVM *jvm;
JNIEXPORT void JNICALL Java_com_comp_prod_main(JNIEnv *env,
jclass thiz) {
LOGV("Main called %d", __LINE__);
//this is how to cache it for other threads
jint rs = (*env)->GetJavaVM(env, &jvm);
assert (rs == JNI_OK);
main();
jvm = NULL;
}
JNIEnv *getJNIEnv(void) {
JNIEnv *env;
jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
assert (rs == JNI_OK);
if(env == NULL)
{
LOGV("env is NULL");
}
return env;
}
从 Java 调用:
Runnable runTerm = new Runnable() {
public void run() {
// call main()
Log.i(TAG, "About to call main on the c!");
try {
Terminal.main();
} catch (IOException e) {
e.printStackTrace();
}
}
};
t = new Thread(runTerm, "C thread");
t.start();