p58-p61

com_darren_day15_Simple1.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_darren_day15_Simple1 */

#ifndef _Included_com_darren_day15_Simple1
#define _Included_com_darren_day15_Simple1
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_darren_day15_Simple1
* Method: sort
* Signature: ([I)V
*/
JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_sort
(JNIEnv *, jclass, jintArray);

#ifdef __cplusplus
}
#endif
#endif

Simple1.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package com.darren.day15;

import java.util.Collections;

import javax.naming.ldap.SortControl;

public class Simple1 {
private static String name;// 一大堆变量
private static String name1;// 一大堆变量
private static String name3;// 一大堆变量

static {
System.load("C:/Users/hcDarren/Desktop/android/NDK/NDK_Day15_VS/x64/Debug/NDK_Day15_VS.dll");
}

public Simple1() {

}

public static void main(String[] args) {
// 1. 数组处理的一些细节
/*
* int[] arr = {11,22,-3,2,4,6,-15};
*
*
* sort(arr);
*
* for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]+"\t");
* }
*
* // 2. 局部引用和全局引用 // localRef();
*
* // saveGlobalRef("Darren");
*
* // System.out.println(getGlobalRef());
*
* // 合适的时机去释放 // delteGlobalRef();
*
* // 再次获取 // System.out.println(getGlobalRef());
*
* // 3.缓存策略 static,native层有一大堆方法要去获取 name 属性 // 初始化全局静态缓存
* initStaticCache();
*
* staticLocalCache("Darren");
*
* System.out.println("name = "+name);
*
* staticLocalCache("Jack");// not null
*
* System.out.println("name = "+name);
*
* staticLocalCache("Rose"); // not null System.out.println("name = "
* +name);
*/

// 异常处理(简单讲,C++异常)

try {
exception();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println("name3 = " + name3);
}

private static final native void exception() throws NoSuchFieldException;

private static final native void initStaticCache();

private static final native void staticLocalCache(String name);

private static final native void delteGlobalRef();

private static final native String getGlobalRef();

private static final native void saveGlobalRef(String str);

private static final native void localRef();

private static final native void sort(int[] arr);
}

com_darren_day15_Simple1.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_darren_day15_Simple1 */

#ifndef _Included_com_darren_day15_Simple1
#define _Included_com_darren_day15_Simple1
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_darren_day15_Simple1
* Method: sort
* Signature: ([I)V
*/
JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_sort
(JNIEnv *, jclass, jintArray);

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_localRef
(JNIEnv *, jclass);

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_saveGlobalRef
(JNIEnv *, jclass,jstring);

JNIEXPORT jstring JNICALL Java_com_darren_day15_Simple1_getGlobalRef
(JNIEnv *, jclass);

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_delteGlobalRef
(JNIEnv *, jclass);

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_staticLocalCache
(JNIEnv *, jclass, jstring);

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_initStaticCache
(JNIEnv *, jclass);

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_exception
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

Simple.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "com_darren_day15_Simple1.h"
#include <stdlib.h>

int compare(const jint *number1, const jint *number2){
return *number1 - *number2;
}

// 全局变量
jstring globalStr;

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_sort
(JNIEnv * env, jclass jclz, jintArray jarray){

// 对 jarray 进行排序 (sort)
jint* intArray = (*env)->GetIntArrayElements(env,jarray,NULL);

int length = (*env)->GetArrayLength(env,jarray);

// 第一个参数:void* 数组的首地址
// 第二个参数:数组的大小长度
// 第三个参数:数组元素数据类型的大小
// 第四个参数:数组的一个比较方法指针(Comparable)
qsort(intArray, length, sizeof(int), compare);

// 同步数组的数据给 java 数组 intArray 并不是 jarray ,可以简单的理解为 copy
// 0 : 既要同步数据给 jarray ,又要释放 intArray
// JNI_COMMIT: 会同步数据给 jarray ,但是不会释放 intArray
// JNI_ABORT: 不同步数据给 jarray ,但是会释放 intArray
(*env)->ReleaseIntArrayElements(env,jarray,intArray,JNI_ABORT);
}

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_localRef
(JNIEnv *env, jclass jclz){
// 在 native 层构建的 Java 对象,你不用了该怎么管理?
// native 层开辟的内存由谁管理,你能开辟多大

// 字符串截取,String 对象
jclass str_clz = (*env)->FindClass(env,"java/lang/String");
jmethodID init_mid = (*env)->GetMethodID(env,str_clz,"<init>","()V");
jobject j_str = (*env)->NewObject(env, str_clz, init_mid);

// 还有 100 行代码

// jobject 不要再使用了,要回收 javaGC 的源码
(*env)->DeleteLocalRef(env,j_str);

// 删除了就不能再使用了,C 和 C++ 都需要自己释放内存(静态开辟的不需要,动态开辟的需要)

}

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_saveGlobalRef
(JNIEnv *env, jclass jclz, jstring str){
// 保存全局变量,其他方法需要用到
globalStr = (*env)->NewGlobalRef(env, str);

// NewWeakGlobalRef (java 中的软引用很像) 无法保证对象不为空
}

JNIEXPORT jstring JNICALL Java_com_darren_day15_Simple1_getGlobalRef
(JNIEnv *env, jclass jclz){
return globalStr;
}

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_delteGlobalRef
(JNIEnv *env, jclass jclz){
(*env)->DeleteGlobalRef(env,globalStr);
}

/*JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_staticLocalCache
(JNIEnv *env, jclass jclz, jstring name){
// name属性 赋值操作
// static jfieldID f_id = NULL;// 局部缓存,这个方法会被多次调用,不需要反复的去获取 jfieldID OpenCV WebRtc
if (f_id == NULL){
f_id = (*env)->GetStaticFieldID(env, jclz, "name", "Ljava/lang/String;");
}else{
printf("fieldID is not null\n");
}
(*env)->SetStaticObjectField(env, jclz, f_id, name);
}*/

// 全局静态缓存,在构造函数中初始化的时候会去缓存
static jfieldID f_name_id = NULL;
static jfieldID f_name1_id = NULL;
static jfieldID f_name2_id = NULL;



JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_staticLocalCache
(JNIEnv *env, jclass jclz, jstring name){
// 如果这个方法会反复的被调用,那么不会反复的去获取 jfieldID
(*env)->SetStaticObjectField(env, jclz, f_name_id, name);
}

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_initStaticCache
(JNIEnv *env, jclass jclz){
// 初始化全局静态缓存
f_name_id = (*env)->GetStaticFieldID(env, jclz, "name", "Ljava/lang/String;");
f_name1_id = (*env)->GetStaticFieldID(env, jclz, "name1", "Ljava/lang/String;");
f_name2_id = (*env)->GetStaticFieldID(env, jclz, "name2", "Ljava/lang/String;");
}

JNIEXPORT void JNICALL Java_com_darren_day15_Simple1_exception
(JNIEnv *env, jclass jclz){

// 假设现在想给 ,name 赋值 name3
jfieldID f_id = (*env)->GetStaticFieldID(env, jclz, "name3", "Ljava/lang/String;");

// 好几种方式
// 1. 补救措施 ,name3 我拿 name
// 1.1 有没有异常
jthrowable throwable = (*env)->ExceptionOccurred(env);
/*if (throwable){
// 补救措施,先把异常清除
printf("有异常");
// 清除异常
(*env)->ExceptionClear(env);
// 重新获取 name 属性
f_id = (*env)->GetStaticFieldID(env, jclz, "name", "Ljava/lang/String;");
}*/

// 2. 想给 java 层抛一个异常
if (throwable){
// 清除异常
(*env)->ExceptionClear(env);
// Throw 抛一个 java 的 Throwable 对象
jclass no_such_clz = (*env)->FindClass(env,"java/lang/NoSuchFieldException");
(*env)->ThrowNew(env, no_such_clz,"NoSuchFieldException name3");

return;// 记得 return
}

jstring name = (*env)->NewStringUTF(env, "Darren");
(*env)->SetStaticObjectField(env, jclz, f_id, name);
}