从接触Android的一段时间后,就经常听到JNI这个东东,刚开始,不知是由于对新事物的排斥,还是根本不把它当成一回事,就没有特地地去理他。只是在活跃的社区中零零散散地看到JNI的身影,大致知道所谓的JNI,就是一种不纯的JAVA编程技术,还需要把C/C++给扯进来。这下好了,看到需要C/C++,立马想到的是,有多远离多远。倒不是因为C/C++做过神马恐怖的勾当,而是本人C/C++技艺不精。自此,选择了逃避。
直到,面临毕业,稀里糊涂地投了一份应聘Android软件开发的岗位。当接到面试官的电话,问到“JNI是什么?”的时候,支支吾吾三言四语也说不出个你死我活。最后,面试的结果也是石沉大海,杳无音讯。从此,对JNI的讨厌之情,入骨三分,同时,又多了份感悟:JNI是个令人头痛,却又不得不学的东东。
就这样,找资料,看文档,一步步来,翻过了几座障碍,打通了Java到C的道路,那种喜悦,尽然让我哑然失笑。。。从此,觉得JNI不再那么邪恶。。。继续前行,,,后来发现,仅仅打通了道路,仅仅只能走个字符串,走个指令,想实现复杂的功能时,才知道,了解JNI的原理和规范刻不容缓,于是乎,Download一份英文JNI档案,不分昼夜地研磨,并在这里留下学习的脚印。。。
闲话少说,步入正文。
我们知道,Java应用程序是一处编码,处处运行的,之所以可以这么威风,靠的就是JVM这个东西,那什么是JVM呢,JVM乃Java虚拟机,是一种虚拟技术,位于java应用程序和特定的操作系统之间,担当着“一处编码,处处运行”的重任。他隐藏了操作系统的差异性,使得运行在上层的java程序可以不用管底层到底是神马操作系统。这样,只要你的机子上有JVM,那么你的机子就可以跑java程序,至于你用的是神马操作系统,我不用管。
可是,有滴时候,我们并不能抛开特定的操作系统的特性,而是用纯粹的java来完成我们的应用。虽然,java是多么多么滴强大,但是他也不是万能的。比如,现在我们的应用需要一些特定操作系统的特性,但是java它不支持,怎么办?或者,我们需要的部分核心功能已经存在了,但是是C/C++的库文件,更常见的一个理由是“这个处理过程性能要求高,java性能忒差,满足不了客户要求,用C/C++吧,性能高”!
如此可见,JNI的存在,总有它的理由。但是JNI的使用,我们破坏了java“一处编码,处处运行”的优势,使得我们的应用是“Host-Dependable”。同时,Java是类型安全的,而C/C++不是滴,所以,使用JNI,java这两大特性就荡然无存了。也因此,要不要使用JNI,我们需要三思而后行。。。
扯了这么远,回过头来,JNI是如何使得Java和C/C++想通的?我们知道,Java之所以不能和C/C++想通,最主要的原因就是类型差异。
关于JNI如何处理类型差异的,后面再说。这里,我们看看Java的数据类型String和C语言的Char*类型是在可见的(黑盒)层面如何相互沟通的。
我们使用Java写个类Jni.java:
在使用javac编译该文件生成Jni.class文件后,我们使用javah -jni来生成一个C语言的头文件(关于javah命令的正确使用,请看我的另一个帖子),该文件名称是demo_jni_Jni.h:
可以看到,生成的本地方法中,第一个参数类型是JNIEnv*,是一个指向JNIEnv的指针类型,那么JNIEnv是一个什么类型呢?
JNIEnv是一个指向了一个Pointer,这个Pointer指向了一张函数表,这张函数表中的每一项就是JNI中的一个函数的入口。本地的方法通过查找这张表来调用某个jni函数,来和JVM交互。如图:
第二个参数,如果申明的方法是static类型的,则该参数是一个jclass类型,如果申明的方法是一个非static类型的,则该参数是一个jobject类型。
如果你的方法含有参数,那么从第三个参数开始,就是申明时方法的参数了。
分享到:
相关推荐
本篇文章将深入探讨Android环境下使用NDK进行JNI开发,并通过"hello-jni"项目作为实例,带领读者一步步走进Android NDK的世界。 一、Android NDK概述 Android Native Development Kit(NDK)是一组工具,它允许...
笔者认为,本书最大的特点在于,较全面、系统、深入地讲解了Android系统中的几大重要组成部分的工作原理,旨在通过直接剖析源代码的方式,引领读者一步步深入于诸如Binder、 Zygote、Audio、Surface、Vold、Rild...
在《CITESPACE使用教程.pdf》中,详细步骤和实例将引导用户从安装软件、导入数据,到设置参数、生成可视化图,再到解读结果,步步深入,确保每个使用者都能掌握这一工具。通过学习和实践,科研人员可以充分利用...
本教程将带你一步步了解如何使用JNI技术,通过两个示例项目"Java-JNIHelloWorld"和"C++ -JNIHelloWorld"来深入学习这一主题。 首先,我们需要理解JNI的基本概念。JNI是一个接口,提供了在Java虚拟机(JVM)中调用...
Android NDK 是一个开发工具集,允许Android应用开发者使用C/C++代码来编写部分应用程序,从而利用这些低级语言的高性能和灵活性。这个工具集使得开发者能够利用...掌握这些步骤对于深入学习Android NDK开发至关重要。
本文将深入探讨"Android HelloNDK"这一主题,帮助开发者更好地理解和运用NDK。 首先,我们来理解Android NDK的基本概念。NDK是Android开发中的一个重要组件,它提供了一系列的工具,使得开发者能够在Android平台上...
总的来说,这个资源包为Android NDK开发提供了一个全面的学习路径,从环境搭建到实际应用,再到高级技巧,一步步引导开发者深入理解并熟练掌握NDK编程。通过实践这些文档中的内容,开发者可以提升其在Android平台上...
在IT领域,尤其是在软件开发中,获取硬件设备的唯一标识符是常见的需求,例如硬盘序列号...如果你希望深入学习,可以下载这个压缩包,按照解压密码解压后查看源码,结合你的Java知识,一步步理解并学习其中的实现方法。
在这个21.07的实战教程中,可能会通过实际案例带领开发者一步步实践上述知识点,包括但不限于修改系统行为、添加新功能、优化性能等方面。通过这样的学习,开发者不仅能够增强对Android系统的掌控力,还能提升解决...
JavaCV(Java Computer Vision)是一个Java接口,它为多个计算机视觉库提供了便利...开发者可以利用这些工具执行各种计算机视觉任务,如图像处理、特征检测、人脸识别等,而无需深入学习C++或直接操作OpenCV的原生API。
以下是一步步实现动态权限请求的步骤: 1. **检查权限状态**:首先,我们需要检测应用是否已经拥有拨打电话的权限。这可以通过`TJPermissionManager`类的`checkSelfPermission`方法完成,传入相应的权限字符串。 2...