1. 访问java属性。
1. native接口
public class JniNatice {
public String key = "andnux";
static {
System.loadLibrary("native");
}
public native String accessField();
}
2. c++实现
extern "C" JNIEXPORT jstring JNICALL
Java_top_andnux_jnidemo_JniNatice_accessField(JNIEnv *env, jobject instance) {
jclass jclazz = env->GetObjectClass(instance);
jfieldID fieldID = env->GetFieldID(jclazz, "key", "Ljava/lang/String;");
jstring jstring1 = static_cast(env->GetObjectField(instance, fieldID));
char *cstr = const_cast(env->GetStringUTFChars(jstring1, JNI_FALSE));
char text[30] = "key ";
strcat(text,cstr);
jstring jstring2 = env->NewStringUTF(text);
env->SetObjectField(instance,fieldID,jstring2);
return jstring2;
}
2. 访问java静态属性。
1. native接口
public class JniNatice {
public static String key2 = "andnux";
static {
System.loadLibrary("native");
}
public native String accessStaticField();
}
2. c++实现
extern "C"
JNIEXPORT jstring JNICALL
Java_top_andnux_jnidemo_JniNatice_accessStaticField(JNIEnv *env, jobject instance) {
jclass jclazz = env->GetObjectClass(instance);
jfieldID fieldID = env->GetStaticFieldID(jclazz, "key2", "Ljava/lang/String;");
jstring jstring1 = static_cast(env->GetStaticObjectField(jclazz, fieldID));
char *cstr = const_cast(env->GetStringUTFChars(jstring1, JNI_FALSE));
char text[30] = "key2 ";
strcat(text,cstr);
jstring jstring2 = env->NewStringUTF(text);
env->SetStaticObjectField(jclazz,fieldID,jstring2);
return jstring2;
}
3. 访问java方法。
1. native接口
public class JniNatice {
static {
System.loadLibrary("native");
}
public int randomInt() {
return new Random().nextInt();
}
public native int accessMethod();
}
2. c++实现
extern "C"
JNIEXPORT jint JNICALL
Java_top_andnux_jnidemo_JniNatice_accessMethod(JNIEnv *env, jobject instance) {
jclass jclazz = env->GetObjectClass(instance);
jmethodID jmethodID1 = env->GetMethodID(jclazz, "randomInt", "()I");
jint value = env->CallIntMethod(instance, jmethodID1);
return value;
}
4. 访问java静态方法。
1. native接口
public class JniNatice {
static {
System.loadLibrary("native");
}
public static String randomUUID() {
return UUID.randomUUID().toString().replace("-", "");
}
public native int accessStaticMethod();
}
2. c++实现
extern "C"
JNIEXPORT jint JNICALL
Java_top_andnux_jnidemo_JniNatice_accessStaticMethod(JNIEnv *env, jobject instance) {
jclass jclazz = env->GetObjectClass(instance);
jmethodID jmethodID1 = env->GetStaticMethodID(jclazz, "randomUUID", "()Ljava/lang/String;");
jstring jstring1 = static_cast(env->CallStaticObjectMethod(jclazz, jmethodID1));
return jstring1;
}
5. 访问java构造方法。
1. native接口
public class JniNatice {
static {
System.loadLibrary("native");
}
public native long accessConstructor();
}
2. c++实现
extern "C"
JNIEXPORT jlong JNICALL
Java_top_andnux_jnidemo_JniNatice_accessConstructor(JNIEnv *env, jobject instance) {
jclass jclazz = env->FindClass("java/util/Date");
jmethodID jmethodID1 = env->GetMethodID(jclazz, "", "()V");
jobject jobject1 = env->NewObject(jclazz, jmethodID1);
jmethodID jmethodID2 = env->GetMethodID(jclazz, "getTime", "()J");
jlong jlong1 = env->CallLongMethod(jobject1,jmethodID2);
return jlong1;
}
6. 访问java父类得方法。
1. A类
public class A {
public void a() {
Log.e("A", "aaaaaaaaa");
}
}
2.AA类
public class AA extends A {
@Override
public void a() {
Log.e("A", "AAAAAAAAAA");
}
}
3. native接口
public class JniNatice {
static {
System.loadLibrary("native");
}
public native void accessNonvirtualMethod();
}
4. c++实现
extern "C"
JNIEXPORT void JNICALL
Java_top_andnux_jnidemo_JniNatice_accessNonvirtualMethod(JNIEnv *env, jobject instance) {
jclass jclazz = env->GetObjectClass(instance);
jfieldID jfieldID1 = env->GetFieldID(jclazz, "a", "Ltop/andnux/jnidemo/A;");
jobject jobject1 = env->GetObjectField(instance, jfieldID1);
jclass jclass1 = env->FindClass("top/andnux/jnidemo/A");
jmethodID jmethodID1 = env->GetMethodID(jclass1,"a","()V");
env->CallNonvirtualVoidMethod(jobject1,jclass1,jmethodID1);
}
7. 解决字符串乱码问题。
1. native接口
public class JniNatice {
static {
System.loadLibrary("native");
}
public native long accessConstructor();
}
2. c++实现
extern "C"
JNIEXPORT jstring JNICALL
Java_top_andnux_jnidemo_JniNatice_chineseChars(JNIEnv *env, jobject instance) {
char *c_str = const_cast("张春林");
jclass jclass1 = env->FindClass("java/lang/String");
jmethodID jmethodID1 = env->GetMethodID(jclass1, "", "([BLjava/lang/String;)V");
jbyteArray jbyteArray1 = env->NewByteArray(static_cast(strlen(c_str)));
env->SetByteArrayRegion(jbyteArray1, 0, static_cast(strlen(c_str)),
reinterpret_cast(c_str));
jstring charsetName = env->NewStringUTF("UTF-8");
return static_cast(env->NewObject(jclass1, jmethodID1,
jbyteArray1, charsetName));
// return env->NewStringUTF(c_str);
}
8. 访问JAVA数组。
1. native接口
public class JniNatice {
static {
System.loadLibrary("native");
}
public native void qsort(int [] datas);
}
2. c++实现
extern "C"
JNIEXPORT void JNICALL
Java_top_andnux_jnidemo_JniNatice_qsort(JNIEnv *env, jobject instance, jintArray datas_) {
jint *datas = env->GetIntArrayElements(datas_, NULL);
jint len =(env->GetArrayLength(datas_));
qsort(datas, static_cast(len), sizeof(int),
reinterpret_cast(comparator));
env->ReleaseIntArrayElements(datas_, datas, 0);
}
9. 返回JAVA数组。
1. native接口
public class JniNatice {
static {
System.loadLibrary("native");
}
public native int[] getArray();
}
2. c++实现
extern "C"
JNIEXPORT jintArray JNICALL
Java_top_andnux_jnidemo_JniNatice_getArray(JNIEnv *env, jobject instance) {
jintArray array = env->NewIntArray(10);
jint len = env->GetArrayLength(array);
jint *elems = env->GetIntArrayElements(array, JNI_FALSE);
for (int i = 0; i < len; ++i) {
elems[i] = i;
}
env->ReleaseIntArrayElements(array, elems, 0);
return array;
}
10. 局部引用。
1. native接口
public class JniNatice {
static {
System.loadLibrary("native");
}
public native void localReference();
}
2. c++实现
extern "C"
JNIEXPORT void JNICALL
Java_top_andnux_jnidemo_JniNatice_localReference(JNIEnv *env, jobject instance) {
for (int i = 0; i < 100; ++i) {
jclass jclass1 = env->FindClass("java/util/Date");
jmethodID jmethodID1 = env->GetMethodID(jclass1, "", "()V");
jobject jobject1 = env->NewObject(jclass1, jmethodID1);
env->DeleteLocalRef(jobject1);
}
}
11. 全局引用(弱全局引用类似)。
弱全局引用:
节省内存,在内存不足的时候回收。
可以引用一个不常用的对象,如果为空,临时创建。
创建:NewWeakGlobalRef
销毁:DeleteWeakGlobalRef
1. native接口
public class JniNatice {
static {
System.loadLibrary("native");
}
public native void createGlobalReference();
public native String getGlobalReference();
public native void releaseGlobalReference();
}
2. c++实现
static jstring globalString;
extern "C"
JNIEXPORT void JNICALL
Java_top_andnux_jnidemo_JniNatice_createGlobalReference(JNIEnv *env, jobject instance) {
jstring glob = env->NewStringUTF("哈哈哈哈");
globalString = static_cast(env->NewGlobalRef(glob));
}
extern "C"
JNIEXPORT jstring JNICALL
Java_top_andnux_jnidemo_JniNatice_getGlobalReference(JNIEnv *env, jobject instance) {
return globalString;
}
extern "C"
JNIEXPORT void JNICALL
Java_top_andnux_jnidemo_JniNatice_releaseGlobalReference(JNIEnv *env, jobject instance) {
env->DeleteGlobalRef(globalString);
}
12. 异常处理。
1. native接口
public class JniNatice {
static {
System.loadLibrary("native");
}
public native String exception();
}
2. c++实现
extern "C"
JNIEXPORT jstring JNICALL
Java_top_andnux_jnidemo_JniNatice_exception(JNIEnv *env, jobject instance) {
jclass jclazz = env->GetObjectClass(instance);
jfieldID fieldID = env->GetFieldID(jclazz, "key2", "Ljava/lang/String;");
jthrowable jthrowable1 = env->ExceptionOccurred();
if (jthrowable1 != NULL) {
env->ExceptionClear();
fieldID = env->GetFieldID(jclazz, "key", "Ljava/lang/String;");
}
jstring jstring1 = static_cast(env->GetObjectField(instance, fieldID));
char *ptr = (char *) env->GetStringChars(jstring1, JNI_FALSE);
if (strcmp(ptr, "andnux") != 0) {
jclass jclass1 = env->FindClass("java/lang/IllegalArgumentException");
env->ThrowNew(jclass1, "参数错误");
}
return jstring1;
}
13. 附上签名。
基本类型 | 属性签名 | 方法签名 |
---|---|---|
void | V | () |
boolean | Z | (Z)V |
byte | B | (B)V |
char | C | (C)V |
short | S | (S)V |
int | I | (I)V |
long | J | (J)V |
float | F | (F)V |
double | D | (D)V |
引用类型的描述符:
一般引用类型则为 L + 该类型类描述符 + ;
(注意,这儿的分号“;”只得是JNI的一部分,而不是我们汉语中的分段,下同)
int[ ] 其描述符为[I
float[ ] 其描述符为[F
String[ ] 其描述符为[Ljava/lang/String;
Object[ ]类型的域描述符为[Ljava/lang/Object;
代码链接:https://github.com/andnux/JniDemo