如何使用:
Calling Java from C++ with JNI - CodeProject
c++里的 JNI 类型 和 JAVA 类型的映射关系:
JNI Types and Data Structures
Java Type | Native Type | Description |
---|---|---|
boolean | jboolean | unsigned 8 bits |
byte | jbyte | signed 8 bits |
char | jchar | unsigned 16 bits |
short | jshort | signed 16 bits |
int | jint | signed 32 bits |
long | jlong | signed 64 bits |
float | jfloat | 32 bits |
double | jdouble | 64 bits |
void | void | not applicable |
JNIEnv 具有 thread affinity ,不可跨线程存储使用,否则 coredump:
The only case that I think fits your question is if you start a Java program, call into a native method, then that native method starts up separate threads. In which case, no, you can't share the JNIEnv pointer, because it's tied to a thread. However, you can use the JNI invocation API to access the Java VM from your C++ thread.
解决方法:https://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html
通过attache thread进行 JNIEnv 绑定后无法获得 jclass:
通过系统类加载器进行查找,不会通过应用类加载器进行查找,因此可以加载系统类,但是不能加载非系统类,如自己在java层定义的类会返回NULL。
env->FindClass("xxx/xxx/xxx");//在子线程这样调用是会返回NULLenv->FindClass("java/lang/String");//ok
目前本人的解决办法是,在主线程时去findClass然后当做global保存起来
//下边在主线程执行jclass cls = env->FindClass("xxx/xxx/xxx");jclass globalCls = static_cast<jclass>(env->NewGlobalRef(cls));//一定要使用NewGlobalRef
这个地方一定要使用NewGlobalRef 将它保存,因为JNI默认的生命周期只有方法体内,这个方法执行完,就会被回收。所以用把它保存成全局引用 然后再不用的时候 调用方法释放掉
env->DeleteGlobalRef(globalCls);
其他参考:
JNI踩过的一些坑 - 简书JNI一些坑 pthread创建的子线程没有 _JNIEnv 因为_JNIEnv 是根据线程相关的,所以pthread创建的native线程必须要调用JavaVMd->Att...https://www.jianshu.com/p/be89eac99d4e