前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JNI使用内存相关问题记录

JNI使用内存相关问题记录

作者头像
呱牛笔记
发布2023-05-02 15:34:05
3300
发布2023-05-02 15:34:05
举报
文章被收录于专栏:呱牛笔记呱牛笔记

最近给服务器提供协议编解码库,出现较多内存相关的问题,做个记录,顺便给有相同需求的同学提供参考!

1、C/C++层创建对象,返回指针给Java层,Java层使用该指针作为后续操作的参数,在windows 64位系统中,出现地址无法访问的问题:

参考:https://www.jianshu.com/p/144136be6be9

在java与c构建多实例的案例中,java中对象保存一个long型成员变量,作为对应c实例的指针,jni层在新建c对象后,将对象指针(64位)转成长整型返回给java成员变量保存。然而在某些情况下,调用c实例的方法会出现ACCESS_VIOLATION,并且在windows上会报错,但在linux上就没问题。经过排查,问题最终定位如下:

在jni.h中,关于jlong(java long)的typedef并不是唯一的,在windows上,long总是32位(所以在linux上没问题),所以在jni层将地址转长整型的操作,必须要用__int64(long, long int, long long 都不行)保存变量,并返回给java。

JNIEXPORT jlong JNICALL Java_com_xdja_test_TestJNIUtil_getNativePointer(JNIEnv *env, jobject obj){

    char *key_list = (char *)malloc(200);

    if (key_list == NULL) {

        LOGD("key_list == null");

        return 0;

    }

    memset(key_list, 0, 200);

    printf("getNativePointer: obj:%08x, key_list:%08x,\r\n", obj, key_list);

    //return __int64(key_list); //windows需要返回的是这个地址

    //

    return jlong(key_list);

}

2、本地类对象方法和实例对象方法的声明不同:

//在创建支持的C/C++程序中添加两个方法,分别是非静态和静态,可以使用对应java类的类方法或者实例方法调用这些接口;

public native String stringFromJNI1();

public static native String stringFromJNI2();

extern "C"

JNIEXPORT jstring JNICALL

Java_com_xdja_test_TestJNIUtil_stringFromJNI1(JNIEnv *env, jobject instance) {

    // TODO

    return env->NewStringUTF(returnValue);

}

extern "C"

JNIEXPORT jstring JNICALL

Java_com_xdja_test_TestJNIUtil_stringFromJNI2(JNIEnv *env, jclass type) {

    // TODO

    return env->NewStringUTF(returnValue);

}

参考:https://blog.csdn.net/cloverjf/article/details/78654366?spm=1001.2014.3001.5501

3、Crash调试手段:

Android的NDK调试工具ndk-stack,ndk-stack是ndk开发工具包下提供的好用工具,能结合崩溃日志给出详细分析;

基础用法: ndk-stack -sym 带有符号表的so所在的目录 -dump 崩溃日志:

比如  ~/Library/Android/sdk/ndk/android-ndk-r16b/ndk-stack -sym app/build/intermediates/cmake/debug/obj/arm64-v8a -dump crash.log 

参考:https://blog.csdn.net/ReadyShowShow/article/details/109095211 

如果是给服务器或者Java应用程序使用的JNI库,调试Crash日志的方法,包括常规手段:日志法、return或者注释代码;

如果能从Core-dump中恢复出调用栈,那么调试效率就会高很多了!

补记:20210702

事出蹊跷必有因,在Linux平台运行正常的代码,在Windows平台就会出现异常,原来是Windows平台的calloc申请出来的内存并不会自动清0,导致结构体中指针对象为非法指针,内存释放就出现了野指针操作,崩溃也就不奇怪了!话说不能在同一个地方摔倒两次,但同时在这个地方卡了几天,真是惭愧!

visual studio 2017 中文注释影响代码逻辑,比方:

// 中文注释

if(xxx)  // 这一行被当作是注释了

{

    do_something...

}

switch(value){

    case 0:

    break;

    // 中文注释

    case 1: // 这一行被当作是注释了,导致case分支判断失败,走到了default分支

    break;

    default:

    break;

}


C代码最好是能做一次PC-lint检查内存相关问题,保证代码质量!

呱牛笔记
呱牛笔记
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/06/24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档