1、GetStringUTFChars
用于将 Java 字符串(jstring
)转换为 UTF-8 编码的 C 风格字符串(const char*
)。
必须 在使用完后调用 ReleaseStringUTFChars
释放内存,否则可能导致内存泄漏。
cpp
std::string data_converter::convertJavaStringToCpp(JNIEnv* env, jstring jStr) {
const char* cStr = env->GetStringUTFChars(jStr, nullptr);
std::string result(cStr);
env->ReleaseStringUTFChars(jStr, cStr);
return result;
}
2、NewStringUTF
用于将 C/C++ 的 UTF-8 字符串 转换为 Java 的 jstring
对象。
cpp
const char *cStr = "Hello from C++! 你好!";
jstring javaStr = env->NewStringUTF(cStr);
3、GetArrayLength
用于获取 Java 数组的长度。
cpp
JNIEXPORT jint JNICALL Java_Example_getArrayLength(JNIEnv *env, jobject obj, jintArray arr) {
jsize length = env->GetArrayLength(arr);
return length;
}
4、GetObjectArrayElement
用于从 Java 对象数组中获取指定索引处的元素。
对于基本类型数组(如 int[], float[] 等),不能直接使用 GetObjectArrayElement,而应该使用对应的函数如 GetIntArrayElements。
cpp
JNIEXPORT void JNICALL Java_Example_printArrayElements(JNIEnv *env, jobject obj, jobjectArray arr) {
jsize length = env->GetArrayLength(arr);
for (jsize i = 0; i < length; i++) {
jobject element = env->GetObjectArrayElement(arr, i);
// 对 element 进行操作...
}
}
5、GetByteArrayRegion
用于将 Java 字节数组 (jbyteArray
) 的一部分或全部复制到 C/C++ 的本地缓冲区中。
cpp
JNIEXPORT void JNICALL Java_Example_processByteArray(
JNIEnv *env,
jobject obj,
jbyteArray javaArray)
{
// 获取数组长度
jsize length = env->GetArrayLength(javaArray);
// 分配本地缓冲区
jbyte *buffer = new jbyte[length];
// 复制整个数组到本地缓冲区
env->GetByteArrayRegion(javaArray, 0, length, buffer);
// 处理数据...
for (jsize i = 0; i < length; i++) {
// 处理 buffer[i]...
}
// 释放本地缓冲区
delete[] buffer;
}
6、(void)env;
和 (void)instance;
这两行是用于 显式忽略未使用参数 的编程技巧。
cpp
static void saveDeviceID(JNIEnv* env, jobject instance, jstring devID)
{
(void)env; // 明确表示不使用 env 参数
(void)instance; // 明确表示不使用 instance 参数
// ...
}
7、GetObjectClass
用于在 C/C++ 代码中获取 Java 对象的类引用。它通常在编写本地方法(native methods)时使用。
cpp
#include <jni.h>
JNIEXPORT void JNICALL Java_Example_printClassName(JNIEnv *env, jobject obj) {
// 获取传入对象的类
jclass cls = env->GetObjectClass(obj);
// 获取类名
jmethodID mid_getName = env->GetMethodID(cls, "getName", "()Ljava/lang/String;");
jstring name = (jstring)env->CallObjectMethod(cls, mid_getName);
const char *str = env->GetStringUTFChars(name, NULL);
printf("Class name: %s\n", str);
env->ReleaseStringUTFChars(name, str);
}
替代方案
如果你想获取某个已知类的引用(而不是通过对象实例),可以使用 FindClass()
函数:
cpp
jclass cls = env->FindClass("java/lang/String");
GetObjectClass()
主要用于当你已经有一个对象实例但需要访问其类信息时使用。
8、NewGlobalRef
用于创建一个全局引用(global reference)到 Java 对象。全局引用在本地代码中跨多个本地方法调用时保持有效,直到显式释放。
cpp
// 全局变量存储引用
jclass globalClassRef;
JNIEXPORT void JNICALL Java_Example_init(JNIEnv *env, jobject obj) {
// 获取局部引用
jclass localClassRef = env->GetObjectClass(obj);
// 创建全局引用
globalClassRef = (jclass)env->NewGlobalRef(localClassRef);
// 局部引用不再需要时可以删除
env->DeleteLocalRef(localClassRef);
}
JNIEXPORT void JNICALL Java_Example_cleanup(JNIEnv *env, jobject obj) {
// 不再需要时释放全局引用
if (globalClassRef != NULL) {
env->DeleteGlobalRef(globalClassRef);
globalClassRef = NULL;
}
}
相关函数
-
DeleteGlobalRef()
: 释放全局引用 -
NewLocalRef()
: 创建局部引用 -
NewWeakGlobalRef()
: 创建弱全局引用
9、
cpp
NetworkManagerCallback() = default;
virtual ~NetworkManagerCallback() = default;
NetworkManagerCallback(const NetworkManagerCallback& other) = delete;
NetworkManagerCallback& operator=(const NetworkManagerCallback& other) = delete;
这几行代码展示了一个类中常见的特殊成员函数的声明和定义方式。
-
NetworkManagerCallback() = default;
-
使用编译器生成的默认构造函数
-
示例:当创建
NetworkManagerCallback
对象时,会调用这个默认构造函数
cppNetworkManagerCallback callback; // 使用默认构造函数
-
-
virtual ~NetworkManagerCallback() = default;
-
声明虚析构函数并使用默认实现
-
使得这个类可以作为基类被继承,且能正确调用派生类的析构函数
-
示例:
cppclass DerivedCallback : public NetworkManagerCallback { ~DerivedCallback() override { /* 清理资源 */ } };
-
-
NetworkManagerCallback(const NetworkManagerCallback& other) = delete;
-
禁用拷贝构造函数
-
示例:以下代码会编译错误
cppNetworkManagerCallback cb1; NetworkManagerCallback cb2(cb1); // 错误:拷贝构造函数被删除
-
-
NetworkManagerCallback& operator=(const NetworkManagerCallback& other) = delete;
-
禁用拷贝赋值运算符
-
示例:以下代码会编译错误
cppNetworkManagerCallback cb1; NetworkManagerCallback cb2; cb2 = cb1; // 错误:拷贝赋值运算符被删除
-
这种模式通常用于:
-
需要作为基类但不需要拷贝功能的类(如回调接口)
-
只允许移动不允许拷贝的类
-
单例模式实现