前言:初学逆向 请多多指教 昨天在看雪论坛发了篇文章,被标记了优秀,不由得感叹 这一个月没有白学! 剩下还有11个月 冲了

学习到的内容

1、了解了什么是NDK,以及在android studio中的环境搭建中注意的事项

2、pthread_create函数调用的学习

3、android的进程中的JavaVM与JavaEnv结构体

4、JNIEnv结构体在c/c++中的不同点

什么是NDK

NDK:NDK是一系列工具的集合,它是集成了交叉编译器,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk

为什么需要Android NDK?

1、效率问题

2、 跨平台程序的移植

我们知道在Android上层APP应用都是通过java写出来的.但是当我们设计游戏或视频,音频程序时,肯定需要完成一些复杂的数学运算,这些复杂的操作基本都是放在底层的库中运行的,而且不是通过java语言写出来的,因为java是基于虚拟机的,比C直接面向CPU的执行效率要低很多

环境搭建,Android Studio在SDK Manager中安装如下两个包SDK工具包:

创建一个新的Android工程,拖到最下面选择Native c++

注意:

1、如果有报错信息为NDK not configured,自己检查下当前工程是否配置了ndk的路径,FILE-Project Structure - SDK Location中ndk的配置路径,然后再去检查是否配置了NDK的环境变量

继续来看CMakeLists.txt中的内容,CMakeLists文本中有规范编译的说明

1、cmake_minimum_required 来表注 cmake的最低版本号的要求

1、设置编译出来的共享连接库文件的名字

2、设置编译的类型

3、设置被编译的源文件的名字

ndkbuild 通过build.gradle的android->defaultConfig中来标注需要生成的对应的处理器类型和位数的共享链接库文件

如果想要让cmake编译的话,可在android->defaultConfig 中添加,标注需要生成的对应的处理器类型和位数的共享链接库文件

结果生成的apk的lib目录下就只有对应的arm v7a的共享链接库文件

pthread_create函数的学习

这里就简单实现两个demo,一个是单参数,一个是多参数

需要注意的就是运行的时候,在主线程中需要设置pthread_join让主线程进行堵塞,防止主线程执行完了 子线程还没执行,这个是基础了 大家肯定也知道,自己就做个笔记!

单参数

#include #include #include #include #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "MYNATIVE", __VA_ARGS__);void* test(void* args){    for(int i=0;iint*)args;i++){        LOGD("test: %d", i);    }    return 0;}extern "C" JNIEXPORT jstring JNICALLJava_com_example_myndkstudy_MainActivity_stringFromJNI(        JNIEnv* env,        jobject /* this */) {    pthread_t pthread;    int iNum = 10;    void* iValue = NULL;    pthread_create(&pthread, NULL, test, &iNum);    pthread_join(pthread, &iValue);    LOGD("pthread return value: %d", iValue);    std::string hello = "Hello from C++";    return env->NewStringUTF(hello.c_str());}

所谓的多参数,其实就是传递参数的时候放一个结构体就好了

#include #include #include #include #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "MYNATIVE", __VA_ARGS__);struct People{    int age;    std::string name;};// 子线程void* test(void* args){    People people = *(People*)args;    LOGD("test: %d", people.age);    LOGD("test: %s", people.name.c_str());    pthread_exit(0);}extern "C" JNIEXPORT jstring JNICALLJava_com_example_myndkstudy_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) {    /* thread test */    pthread_t pthread;    People people = {20,"我就想睡觉"};    pthread_create(&pthread, NULL, test, &people);    pthread_join(pthread, NULL);    std::string hello = "Hello from C++";    return env->NewStringUTF(hello.c_str());}

进程中的JavaVM和JavaEnv

先知道JNI_OnLoad是什么时候执行顺序的?

array_init -> init_array -> JNI_OnLoad

如何获取JNIEnv 和 JavaVM:

通过JavaVM的attachCurrentThread 子线程中获取JNIEnv

通过JavaVM的GetEnv在主线程中获取JNIEnv

注意:

1、子线程attachCurrentThread获取完JNIEnv,用完之后还需要释放DetachCurrentThread,但是在主线程中通过attachCurrentThread去获取JNIEnv也是可以获取成功的!

2、通过JavaVM的GetEnv,只能在主线程中获取JNIEnv,如果在子线程中获取会获取失败

3、重点,JNI_OnLoad返回值一定要返回对应的JNI版本,一般都是返回JNI_VERSION_1_6,否则程序会报错

最终展示的结果:

1、JavaVM对象在art虚拟机中的进程中是唯一的

2、JNIEnv对象在art虚拟机中的进程中并不是唯一的,而是多个

JavaEnv结构体在c/c++中的不同点

为了更好的学习JavaVM 和 JNIEnv,那么就需要了解的透彻,先从结构体下手

在学习的时候都看到在C中对 JNIEnv对象调用方法的时候,都需要先对env解引用一次,然后再去调用jni的方法,比如ida中就有对应的例子,比如:

继续跟一层,可以看到如下,其实本质是跟C一样的

所以这里就来学习为什么两种调用方式是不同的,其实这里就是c++会帮助我们来封装函数,追究到底还是得研究jni.h的定义

先跟进JNIEnv,可以发现对于JNIEnv定义 c++和c的定义是不同的,c++会给它起一个别名,而c就直接就是JNINativeInterface结构体指针

继续跟_JNIEnv这个别名

继续跟_JNIEnv,发现原来JNINativeInterface结构体指针也在_JNIEnv中,但是会发现下面的内容是对于c++来定义的

首先看GetVersion这个函数,你会发现它最终还是进去了functions这个JNINativeInterface结构体指针,然后最终调用了JNINativeInterface结构体中的GetVersion

jint GetVersion(){ return functions->GetVersion(this); }

所以很简单,其实就是c++帮助我们封装了一层函数,让我们间接来调用,在调用的时候c++会帮我们传入一个this指针,也就是图中红框的地方

但是在C中,当正常的调用GetVersion这个函数指针的时候,它需要一个JNIEnv的指针,但是c++会帮我们传进去,所以c++调用的时候就可以不用参数直接进行调用

文章对你是否有帮助?有的话就点个?吧!!!

androidstudio jni开发_初识NDK开发(一)相关推荐

  1. 安卓开发学习之初识ndk开发

    背景 今天没事干,就开始学习ndk开发,实现了一下Android和C的函数方法互调,记录一下步骤 步骤 1.通过Android Studio的SDK Manager安装CMake.LLDB和NDK 2 ...

  2. android应用程序开发_深圳app开发公司:跨平台应用程序开发工具有哪些?

    深圳app开发公司:跨平台应用程序开发工具有哪些?跨平台应用程序开发工具的出现是移动开发的发展和竞争的结果.对更快.更经济的应用程序开发的追求导致了跨平台技术的出现.在移动应用程序开发工具推荐中,哪些 ...

  3. pythonqt4上位机开发_上位机开发之单片机通信实践(一)

    经常会有一些学员会问到上位机与单片机之间通信的问题,而我们经常会讲上位机与PLC之间通信,那么其实对上位机开发来说,不管是和PLC通信,还是和单片机通信,通信原理都是一样的.PLC的本质就是单片机,在 ...

  4. 简单Android app开发_什么方法开发APP最简单?试试0代码开发平台

    开发APP有哪些方式? 说到开发APP,那肯定是找外包公司最方便,只用花钱就能坐等APP完成.但是,现在需要开发APP的公司范围越来越广,传统外包公司高昂的费用显然已经不能普罗大众,那么,有没有简单便 ...

  5. python自动化工具开发_初识TPOT:一个基于Python的自动化机器学习开发工具

    1. TPOT介绍 一般来讲,创建一个机器学习模型需要经历以下几步: 数据预处理 特征工程 模型选择 超参数调整 模型保存 本文介绍一个基于遗传算法的快速模型选择及调参的方法,TPOT:一种基于Pyt ...

  6. iOS开发_初识视频直播

    一.使用第三方ijkPlayer框架开发直播 1.去到B站得github主页,找到ijkplayer项目,下载源码 ijkplayer下载地址 2.Demo的使用以及如何编译Demo 请移步如何快速的 ...

  7. jni java共享变量_JNI/NDK开发指南(七)——C/C++访问Java实例变量和静态变量 .

    在上一章中我们学习到了如何在本地代码中访问任意Java类中的静态方法和实例方法,本章我们也通过一个示例来学习Java中的实例变量和静态变量,在本地代码中如何来访问和修改.静态变量也称为类变量(属性), ...

  8. android ndk 界面开发教程,Android NDK开发之入门教程

    JNI(Java Native Interface, Java本地化方法)使得Java能与其它语言(如C.C++)的动态库进行交互. 在Android 项目中,经常看到地图,统计,推送之类的第三方平台 ...

  9. 面向表开发 面向服务开发_面向繁忙开发人员的计算机视觉

    面向表开发 面向服务开发 This article is part of a series introducing developers to Computer Vision. Check out o ...

最新文章

  1. JDBC编程:2(数据库的基本操作)
  2. “三巨头”联合发布万字长文,深度学习将通往何方?
  3. CentOS查看CPU信息、位数、多核信息
  4. 自考c语言程序设计,自考“C语言程序设计”模拟试题八
  5. SpringCloud动态获取yml文件里面的自定义配置
  6. 计算机操作系统——页面置换算法
  7. hdu 3367 Pseudoforest (最大生成树 最多存在一个环)
  8. springboot的核心
  9. python自带的shell、其性能优于ipython吗_Python自带的shell,其性能优于IPython
  10. Java代码总结【1】_查询手机号码归属地
  11. php定位和天气,基于thinkphp实现依据用户ip判断地理位置并提供对应天气信息的应用...
  12. (三)构建dubbo分布式平台-maven模块规划
  13. 亲测,终于知道为什么这本 Python 书销量超过13W+!
  14. 最小高度100%页脚保持在底部的布局方法
  15. 解决办法:C代码中明明有,为什么编译时提示未定义的引用
  16. AJAX from S3 CORS fails on preflight OPTIONS with 403
  17. linux 移动硬盘位置,在linux中使用移动硬盘
  18. API卡_什么是图形API,API又是用来做什么的,其实它是一名出色的翻译官
  19. 透视投影的原理和实现
  20. 如何通过努力出书,如何写有畅销资质的书,本文汇集了多位计算机图书作者的经验

热门文章

  1. 如何向非技术人员解释“稀疏傅里叶变换”算法?
  2. Codeforces 900D Unusual Sequences:记忆化搜索
  3. 使用VS Code开发.Net Core 2.0 MVC Web应用程序教程之三(配置文件读取)
  4. 一个winform带你玩转rabbitMQ
  5. dispatch_queue_create(com.biostime.xxx, DISPATCH_QUEUE_SERIAL)的陷阱
  6. 121-Best Time to Buy and Sell Stock
  7. 基于node.js的压缩合并安装
  8. VS2010 发布web项目 问题
  9. 又偷懒了4个月,督促自己
  10. memset函数详细说明