Android JNI调用(一)
1.jni的基本工作原理 (1)java的本质 想搞明白jni的本质,还要从java的本质说起.从本质上来说,java这门语言就是一门脚本语言(这是偶的个人理解,希望java大侠们不要用板砖拍我),它的运行完全依赖于脚本引擎对java的代码进行解释和执行(当然了,现代的java已经先进许多,可以从源代码编译成.class之类的中间格式的二进制文件,这种处理会大大地加快
·
1.jni的基本工作原理
(1)java的本质
想搞明白jni的本质,还要从java的本质说起.从本质上来说,java这门语言就是一门脚本语言(这是偶的个人理解,希望java大侠们不要用板砖拍我),它的运行完全依赖于脚本引擎对java的代码进行解释和执行(当然了,现代的java已经先进许多,可以从源代码编译成.class之类的中间格式的二进制文件,这种处理会大大地加快java脚本的运行速度,但是基本的执行方式仍然不变,由脚本引擎(我们称之为JVM)来执行,与python、perl之类的纯脚本相比,它只是把脚本变成了二进制格式而已.另外就是java本身对面向对象的概念支持得很好,拥有完善的功能库可供调用,把这个脚本引擎移植到所有平台上,那么这个脚本自然就实现所谓的“跨平台”了).绝大多数的脚本引擎都支持一个很显著的特性,就是可以通过c/c++编写模块,在脚本中调用这些模块,以此来类比java,也是一样的,java一定要提供一种在脚本中调用c/c++编写的模块的机制,才能称得上是一个相对完善的脚本引擎.
(2)android中的java
android平台从本质上是 由arm-linux操作系统 和一个叫做dalvik的java虚拟机组成的.所有在android模拟器上面看到的那些华丽的界面,都是用java语言编写的(参见android平台源代码的frameworks/base目录).目前看来dalvik只是提供了一个标准的支持jni调用的java虚拟机环境.android平台中所有的硬件相关的操作均是采用jni技术进行了封装,由java去调用jni模块,而jni模块使用c/c++调用android本身的arm-linux底层驱动.
例如,frameworks/base/libs/ui目录下面有一个叫做“EGLDisplaySurface.cpp”的文件,里面的:
status_t EGLDisplaySurface::mapFrameBuffer()函数中,就有直接对android的arm-linux中的framebuffer的初始化代码.
这也更加印证了,android其实是依靠java+jni建立起来的王国.hoho,如此一来,就凸显出jni在Android开发中的重要性(当然,一些简单的小程序是完全可以只用java就搞定的).
“jni”的子目录,这个目录将用来存放.c的文件.
(3)编写jni模块的java调用类
这是必然的了,jni嘛,一定要有调用者才能够工作在src的最内层目录里面添加一个叫做JniModule.java的原文件,看上去如下所示:
java代码:
注意,偶们最终会生成一个叫做libaaaa.so的arm兼容的二进制动态库,但是在使用System.loadLibrary动态载入的时候,只需要填写lib和.so之间的名字aaaa即可,在此实验的功能仅仅是两个数字a和b的求和计算以及如何在jni的c语言模块中把log日志打印到logcat中.
在JniTest.java中,偶们可以如下调用这个类:
java代码:
注意,这里的button3是很重要的,功能是得到当前程序的进程id,然后显示地杀掉它!
为什么要这么做呢?原因在于,android里面的常规退出函数并没有真正地关闭当前运行的进程,而是切换到后台去了。这对普通的java应用看上去很平常,而且可以加速再次启动该程序的速度,但是对于带有jni模块的java程序而言就是恶梦,因为程序没有真的关闭。所以那个libaaaa.so库,会一直停留在内存中,这时候如果你希望把旧的so库替换成新的库,那就要重启手机才行。。。很痛苦,所以想到了这种办法,直接杀掉自己,那么下一次启动的时候就会自动重新载入最新的so库。
(1)java的本质
想搞明白jni的本质,还要从java的本质说起.从本质上来说,java这门语言就是一门脚本语言(这是偶的个人理解,希望java大侠们不要用板砖拍我),它的运行完全依赖于脚本引擎对java的代码进行解释和执行(当然了,现代的java已经先进许多,可以从源代码编译成.class之类的中间格式的二进制文件,这种处理会大大地加快java脚本的运行速度,但是基本的执行方式仍然不变,由脚本引擎(我们称之为JVM)来执行,与python、perl之类的纯脚本相比,它只是把脚本变成了二进制格式而已.另外就是java本身对面向对象的概念支持得很好,拥有完善的功能库可供调用,把这个脚本引擎移植到所有平台上,那么这个脚本自然就实现所谓的“跨平台”了).绝大多数的脚本引擎都支持一个很显著的特性,就是可以通过c/c++编写模块,在脚本中调用这些模块,以此来类比java,也是一样的,java一定要提供一种在脚本中调用c/c++编写的模块的机制,才能称得上是一个相对完善的脚本引擎.
(2)android中的java
android平台从本质上是 由arm-linux操作系统 和一个叫做dalvik的java虚拟机组成的.所有在android模拟器上面看到的那些华丽的界面,都是用java语言编写的(参见android平台源代码的frameworks/base目录).目前看来dalvik只是提供了一个标准的支持jni调用的java虚拟机环境.android平台中所有的硬件相关的操作均是采用jni技术进行了封装,由java去调用jni模块,而jni模块使用c/c++调用android本身的arm-linux底层驱动.
例如,frameworks/base/libs/ui目录下面有一个叫做“EGLDisplaySurface.cpp”的文件,里面的:
status_t EGLDisplaySurface::mapFrameBuffer()函数中,就有直接对android的arm-linux中的framebuffer的初始化代码.
这也更加印证了,android其实是依靠java+jni建立起来的王国.hoho,如此一来,就凸显出jni在Android开发中的重要性(当然,一些简单的小程序是完全可以只用java就搞定的).
“jni”的子目录,这个目录将用来存放.c的文件.
(3)编写jni模块的java调用类
这是必然的了,jni嘛,一定要有调用者才能够工作在src的最内层目录里面添加一个叫做JniModule.java的原文件,看上去如下所示:
java代码:
注意,偶们最终会生成一个叫做libaaaa.so的arm兼容的二进制动态库,但是在使用System.loadLibrary动态载入的时候,只需要填写lib和.so之间的名字aaaa即可,在此实验的功能仅仅是两个数字a和b的求和计算以及如何在jni的c语言模块中把log日志打印到logcat中.
在JniTest.java中,偶们可以如下调用这个类:
java代码:
注意,这里的button3是很重要的,功能是得到当前程序的进程id,然后显示地杀掉它!
为什么要这么做呢?原因在于,android里面的常规退出函数并没有真正地关闭当前运行的进程,而是切换到后台去了。这对普通的java应用看上去很平常,而且可以加速再次启动该程序的速度,但是对于带有jni模块的java程序而言就是恶梦,因为程序没有真的关闭。所以那个libaaaa.so库,会一直停留在内存中,这时候如果你希望把旧的so库替换成新的库,那就要重启手机才行。。。很痛苦,所以想到了这种办法,直接杀掉自己,那么下一次启动的时候就会自动重新载入最新的so库。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)