jni指针和堆栈注意

注意

1、c中指针可以直接转为java里的int值,都是32位无损失。

2、循环里要注意释放本地引用,因为循环太多或不可预知,容易溢出,你没有做着咯额异常处理,jvm会直接退出,看不到打印堆栈信息的,所以使用jni时如果程序没有打印就无故退出,就检查下本地方法。

3、long 对应J不是L,会给出打印信息提示的。


事例:

事例1、转成long了,它在java里是64位的,这个文件指针,我在java函数作用域是有效的,递归调用也可以,所以,不会被回收,需要手动关闭资源。

jlong Java_fang_android_OS_opendir(JNIEnv* env, jobject clazz, jstring jPath)
{
	__android_log_print(ANDROID_LOG_INFO,LOG_TAG, "");
	ScopedUtfChars path(env,jPath);
	//li(path);

	DIR* d = NULL;
	d = opendir(path);
	__android_log_print(ANDROID_LOG_INFO,LOG_TAG,"sizeof(DIR*) = %d, %p", sizeof(DIR*), d);
	//li("sizeof(DIR*) = %d, %p", sizeof(DIR*), d);
	return PtrToLong(d);
}



//readdir() 不是线程安全的,因为所返回的结构是存储在函数库中的一个静态变量。
//大多数现代的 UNIX 系统都具有线程安全的 readdir_r(),如果您正在编写线程代码,可以使用这个函数作为替代。
jstring Java_fang_android_OS_readdir(JNIEnv* pEnv, jobject clazz, jlong dir, jintArray fileinfo)
{
	dirent dirEntry, *entryPtr;
	int retval = readdir_r((DIR*)(long)dir, &dirEntry, &entryPtr);
	if (entryPtr == NULL || 0 != retval)
		return NULL;
//	dirent *pDirEntry = readdir((DIR*)(long)dir);
//	if (pEnv->ExceptionCheck()) {
//            return NULL;
//    }
//	if(NULL== pDirEntry){
//		return NULL;
//	}
	//li(pDirEntry->d_name);
	if(fileinfo != 0){
		jint* pFileInfo = (jint*)pEnv->GetPrimitiveArrayCritical(fileinfo, 0);
		if (pFileInfo)
		{
			int len = pEnv->GetArrayLength(fileinfo);
			if (len >= 4)
			{
				pFileInfo[0] = dirEntry.d_ino;
				pFileInfo[1] = dirEntry.d_off;
				pFileInfo[2] = dirEntry.d_reclen;
				pFileInfo[3] = dirEntry.d_type;
			}
			pEnv->ReleasePrimitiveArrayCritical(fileinfo, pFileInfo, 0);
		}
	}
	return pEnv->NewStringUTF(dirEntry.d_name);
}


jint Java_fang_android_OS_closedir(JNIEnv* env, jobject clazz, jlong dir)
{
	int ret = closedir((DIR*)(long)dir);
	return static_cast<jint>(ret);
}



事例2:

。还是官方代码,稍微转换一下,少依赖其他文件,这里ScopedLocalRef作用域完了会自动释放NewStringUTF的。

	// Translate the intermediate form into a Java String[].
	for (size_t i = 0; i < numEntries; ++i) {
		if (answer) {
			ScopedLocalRef<jstring> localFileNameRef(pEnv, pEnv->NewStringUTF(currentEntry->pathEntry));
			//jstring jstrFileName = pEnv->NewStringUTF(currentEntry->pathEntry);
			if (pEnv->ExceptionCheck()) {
				return NULL;
			}
			//pEnv->SetObjectArrayElement(answer, i, jstrFileName);
			pEnv->SetObjectArrayElement(answer, i, localFileNameRef.get());
			if (pEnv->ExceptionCheck()) {
				return NULL;
			}
			//pEnv->DeleteLocalRef(jstrFileName);
		}
		free((void *) currentEntry);
		currentEntry = currentEntry->next;
		//pEnv->ReleaseStringUTFChars(s, currentEntry->pathEntry);
		//pEnv->DeleteLocalRef( s);
	}


事例3,注册本地函数时

	{"opendir",		"(Ljava/lang/String;)J",						(void*)Java_fang_android_OS_opendir},
	{"closedir",	"(J)I",											(void*)Java_fang_android_OS_closedir},
	{"readdir",		"(J[I)Ljava/lang/String;",						(void*)Java_fang_android_OS_readdir},


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值