- JNI(java native interface)
Java
本地开发接口,JNI
是一个协议,这个协议用来沟通Java
代码和外部的本地代码(c/c++
).
通过这个协议Java
代码就可以调用外部的c/c++
代码,外部的c/c++
代码也可以调用java代码,
使用JNI技术,其实就是在Java程序中,调用C语言的函数库中提供的函数,来完成一些Java语言无法完成的任务。由于Java语言和C语言结构完全不相同,因此若想让它们二者交互,则需要制定一系列的规范。
JNI就是这组规范,此时 Java只和JNI交互,而由JNI去和C语言交互。JNI技术分为两部分:Java端和C语言端。且以Java端为主导。
- 首先,Java程序员在Java端定义一些native方法,并将这些方法以C语言头文件的方式提供给C程序员。
- 然后,C程序员使用C语言,来实现Java程序员提供的头文件中定义的函数。
- 接着,C程序员将函数打包成一个库文件,并将库文件交给Java程序员。
- 最后,Java程序员在Java程序中导入库文件,然后调用native方法。
在Java程序执行的时候,若在某个类中调用了native方法,则虚拟机会通过JNI来转调用库文件中的C语言代码。提示:C代码最终是在Linux进程中执行的,而不是在虚拟机中。
- 为什么要用JNI
- 首先,Java语言提供的类库无法满足要求(驱动开发 wifi等),且在数学运算,实时渲染的游戏上,音视频处理等方面上与C/C++相比效率稍低。
- 然后,Java语言无法直接操作硬件,C/C++代码不仅能操作硬件而且还能发挥硬件最佳性能。
- 接着,使用Java调用本地的C/C++代码所写的库,省去了重复开发的麻烦,并且可以利用很多开源的库提高程序效率。Opencore
- 接着,特殊的业务场景,java能反编译但是c不能,因此对于一些不想让别人知道的东西可以用c,加密等
- 怎么用JNI
- C/C++语言
- 掌握java jni流程
- NDK (native develop kits )
- 指针和指针变量的关系
指针就是地址,地址就是指针
地址就是内存单元的编号
指针变量是存放地址(指针)的变量
指针和指针变量是两个不同的概念
但是要注意: 通常我们叙述时会把指针变量简称为指针,实际它们含义并不一样
- 未经过初始化的指针变量,不能够直接使用
- 指针变量的类型 不能够相互转换
- 函数的变量(静态)不能够跨函数访问,失去了函数变量的访问范围(生命周期),因为方法执行完之后会释放内存,所以方法中的变量就没有了,
但是地址值还是能拿到的,因为地址值是内存中真实存在的地址位置 - 指针声明的三种方式
int * p; //p 是变量的名字, int * 是一个类型,这个变量存放的是int类型变量的地址。
int* p int * p int *p
-
*号的三种含义
- 乘法 3*5
- 定义指针变量 int * p;
- 指针运算符,如果p是一个已经定义好的指针变量,则*p表示以p的内容为地址的变量
- 为什么要使用指针(指针的重要性)
直接访问硬件 (opengl 显卡绘图)
快速传递数据(指针表示地址)
返回一个以上的值(返回一个数组或者结构体的指针)
表示复杂的数据结构(结构体)
方便处理字符串
指针有助于理解面向对象 -
指针和数组的关系
一维数组的数组名是个指针常量,它存放的是一维数组第一个元素的地址
C中数组的定义比较死板,中括号必须放到名字的后面
int a[5];
printf(“%#X\n”,&a[0]);
printf(“%#X\n”,&a);如果p是一维数组 则p[i] 等价于 *(p+i),都是得到一维数组中的第i个元素。
在c语言中不会检查角标越界如int a[5]写a[5]不会报错 -
动态分配内存Malloc
- 静态内存和动态内存
静态内存是系统是程序编译执行后系统自动分配,由系统自动释放,静态内存是栈分配的.动态内存是堆分配的.
C中静态内存会自动释放,但是对于动态内存(堆内存)在c中是没有垃圾回收的,必须要靠程序员手动的去释放,不然就会一直存在 -
C中的基本数据类型
char, int, float, double, signed, unsigned, long, short and void
c中char 占用1个字节 java char占用2个字节
c中long 占用4个字节 java long占用8个字节int flag = 0,1 表示java中boolean类型
c中用char数组 来表示java中String类型或者指针方式来表示java中String类型
//内部转化为一个字符串的数组,并且在数组的最后一个元素拼装一个\0.
char* cc = “heima 15″;//char* str =”hello” ; //<--> char str[] ={‘h’,’e’,’l’,’l’,’o’,’\0′};
char cc[20] = “heima 15”;
char cc[20] = {‘h’,’e’,’i’,’m’,’a’}; -
c文件的后缀是.c
- C中的输入输出
%d – int
%ld – long int
%c – char
%f – float
%lf – double
%x – 十六进制输出 int 或者long int 或者short int
%#x – 以0x开头 十六进制输出 int 或者long int 或者short int
%o – 八进制输出
%s – 字符串 -
c语言从键盘输入一个字符串
- 取地址符 &(能得到一个对象的地址)
-
C中两个数的交换
- C中的for循环
- 指针的运算
int i = 3; //天津 解放路 33号
int j = 5; // 北京 东北旺 9号
int* p = &i;
int* q = &j;
//p-q; 单纯的指针相加减 是没有任何的意义的.
//指针的运算只有在连续的内存空间里面(数组) 才有意义.
因为指针的运算必须在数组中才有效,这就是为什么数组中能用
p[i] 等价于 *(p+i),因为这个p是数组的名字也代表了数组中第一个元素的地址,p+i就是讲指针加几就是得到第几个元素的指针 -
函数的指针
- 结构体(类似于java中的类)
结构体的三种写法
第一种第二种
第三种
- Union联合体
- 枚举
- typedef
定义别名
声明自定义数据类型,配合各种原有数据类型来达到简化编程的目的的类型定义关键字。每一个指针占四个字节
-
多级指针
C语言常见术语:
库函数:
- 为了代码重用,在C语言中提供了一些常用的、用于执行一些标准任务(如输入/出)的函数,这些函数事先被编译,并生成目标代码,然后将生成的目标代码打包成一个库文件,
以供再次使用。 库文件中的函数被称为库函数,库文件被称为函数库。
通过头文件的方式 把函数库里面所有的函数暴露 .h - 在Windows中C语言库函数中的目标代码都是以.obj为后缀的,Linux中是以 .o为后缀。
提示:单个目标代码是无法直接执行的,目标代码在运行之前需要使用连接程序将目标代码和其他库函数连接在一起后生成可执行的文件。Windows ->.exe .dll
Linux -> .so 动态库
.a 静态库
头文件:
- 头文件中存放的是对某个库中所定义的函数、宏、类型、全局变量等进行声明,它类似于一份仓库清单。若用户程序中需要使用某个库中的函数,
则只需要将该库所对应的头文件include到程序中即可。 - 头文件中定义的是库中所有函数的函数原型。而函数的具体实现则是在库文件中。
- 简单的说:头文件是给编译器用的,库文件是给连接器用的。
- 在连接器连接程序时,会依据用户程序中导入的头文件,将对应的库函数导入到程序中。头文件以.h为后缀名。
函数库: - 动态库:在编译用户程序时不会将用户程序内使用的库函数连接到用户程序的目标代码中,只有在运行时,且用户程序执行到相关函数时才会调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。 .so 动态库
- 静态库:在编译用户程序时会将其内使用的库函数连接到目标代码中,程序运行时不再需要动态库。使用静态库生成可执行文件比较大。
在Linux中:
- 静态库命名一般为:lib+库名+.a 。
- 如:libcxy.a 其中lib说明此文件是一个库文件,cxy是库的名称,.a说明是静态的。
- 动态库命名一般为:lib+库名+.so 。.so说明是动态的。
Windows 下的动态库 .dll