入门JNI需要知道的(一)

来源:互联网 发布:日本南北朝 知乎 编辑:程序博客网 时间:2024/06/03 20:44

前言

什么是JNI

  • java native interface 的简称
  • 在java和本地语言相互调用时,充当两者之间的翻译.
  • 可以看作一种协议(规范),它提供了一套编程框架.

为什么需要JNI

  • 可以很方便的操作底层硬件,例如手机上的传感器等.
  • 提高程序的运行效率,例如2D,3D加速,音视频的解码.
  • 提高程序的安全性,因为本地语言编译之后是二进制的可执行文件(不同的操作系统二进制的可执行文件不同),程序被反编译之后很难看出业务逻辑的具体实现.
  • 方便复用本地开源项目(FFmpeg[多媒体播放器],sqlite,openSSL,openGL,openCV等).
  • 降低程序的移植性等等.

使用需要知道哪些前提

  • 熟悉使用java
  • 了解基本c语言(指针)
  • 熟悉JNI的规范
  • 了解NDK的使用

C

我们应该了解的

  • 两种语言相同的数据类型占用的字节相同时,在传递时不需要进行转换处理.
  • c语言中没有byte,boolean,c语言中非0为真,0为假.(将所有非零真值中的1代表真).
  • c语言中的char(1个字节)和long(4个字节)与java有所区别.
  • c语言中整数类型前面有signed(默认)/ unsigned ,影响着这个整数类型是否能表示负数.
  • sizeof()是一个运算符,计算数据类型大小,返回它参数的字节数.
  • 内存特点
    1. 内存单元的大小是1 byte, 即 8 bits,也就是说:内存单元最大是255.
    2. 内存单元排列是线性连续.
    3. 进程内存单元个数(即内存大小) 在32位平台下,每个进程拥有4G的内存范围(实际用到的内存会映射到实际内存中).
  • 内存单元编号:也就是内存单元在内存中的地址,是在内存中识别内存单元的唯一编号.
  • 指针
    1. 将内存单元的地址(编号)成为指针.
    2. 是一个无符号整数(unsigned int),它是一个以当前系统寻址范围为取值范围的整数.
    3. 32位系统下寻址能力(地址空间)是4G Bytes(0~2^32-1)二进制表示长度为32bits(也就是4Bytes), unsigned int类型也正好如此取值.
  • 指针变量
    1. 普通变量 : 保存数值数据
    2. 指针变量 : 专门保存地址的变量(只保存某个变量的第一个内存单元编号,其中变量是连续的地址空间)
    3. 我们约定这样表示一个指针变量 : 数据类型 * 指针变量名;
    4. 通常指针变量也被叫做指针
  • 指针运算符*和&

    1. &取地址运算符,取变量的地址(编号)
    2. 在定义指针变量时使用的 * 是一个类型标志,代表定义的变量是一个指针变量
    3. * 除了在定义指针变量和类型强转时以外的其他情况使用,都代表指针运算符,例如

      int i = 0;    //定义普通变量int *  p = &i;//定义指针变量,*是类型标志,不是指针运算符              // 也可以写成这样 int *p; p = &i;*p = 30;      // *p <=> i, * 是指针运算符,指向谁就是访问谁 *&i = 20;     // 通过指针访问 *&i <=> i
  • 指针的大小
    • 是确定的,在32位平台下,是4个字节
  • 指针类型和指针的数据类型

    //在这样一段代码中int * p = &i;//int 是指针的数据类型,它不能影响指针的大小,它代表p所指向的变量的数据类型,决定指针在访问内存时一次存取多少字节//int * 合起来才是真正的指针类型,代表p是一个指针变量.
  • 二级指针

    int main(){    int i = 0;    int* p = &i;    //一级指针保存普通变量的地址     int** pp = &p;  //二级指针保存一级指针地址     i = 10;//变量名访问    printf("i = %d\n",i);    *p = 20;//一级指针访问    *p <=> i     printf("i = %d\n",i);    **pp = 30;// 二级指针访问 **pp <=> *p <=> i     printf("i = %d\n",i);    return 0;}
  • 指针的运算

    • 指针的运算只有在一段连续的内存空间上才有意义.(即数组)
    • 指针+整数N,指针p向高地址方向移动了N个对象,编号变化p+N*sizeof(对象类型);
      因为编译器会自动乘.不需要我们画蛇添足.
    • 指针+整数N也是同样的道理.
  • 数组

    • 数组名:数组名代表数组首元素首地址,是一个常量. 例如int a[5]; a <=> &a[0]
    • 数组元素个数计算方法 sizeof(a) / sizeof(a[0])
  • 指针和数组的关系
    • 根据数组和指针的运算, 我们可以得出: 若int a[5] , int * p = a; 则 a[i] <=> * (a + i) <=> * (p + i) <=> p[i].
    • 因为在C语言中, a[5]会被转换成* (a+i)来编译. 简单来说, 当你看到a[?]时, 请自动脑补* (a+?), 而* (a+i)是不会出现越界的情况,因为无论任何时候, 都是可以加减的. 这样也就解释了为什么C语言不能检查索引越界.
0 0