NDK:AndroidNDK是在SDK前面又加上了“原生”二字,即NativeDevelopmentKit,因此又被Google称为“NDK”。
NDK全称:NativeDevelopmentKit。
NDK是一系列工具的集合。
NDK提供了一系列的工具,帮助开发者快速开发C(或C)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。
NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。
NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。
其实:
NDK就是能够方便快捷开发so文件的工具。JNI的过程比较复杂,生成so需要大量 *** 作,而NDK就是简化了这个过程。
AndroidSDK:
SDK(softwaredevelopmentkit)软件开发工具包。被软件开发工程师用于为特定的软件包、软件框架、硬件平台、 *** 作系统等建立应用软件的开发工具的集合。因此!AndroidSDk指的既是Android专属的软件开发工具包
JNI:
JavaNativeInterface(JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI是本地编程接口,它使得在Java虚拟机(VM)内部运行的Java代码能够与用其它编程语言(如C、C和汇编语言)编写的应用程序和库进行交互 *** 作
当然一般需要进行如下 *** 作流程:
1)编写java程序:这里以HelloWorld为例。为了实现在java代码中调用c函数printf。
代码1:
classHelloWorld{
publicnativevoid();
static{
SystemloadLibrary("hello");
}
publicstaticvoidmain(String[]args){
newHelloWorld()();
}
}
声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为native的,并且不能实现。
Load动态库:SystemloadLibrary("hello");
这里一般是以static块进行加载的。同时需要注意的是SystemloadLibrary()的参数“hello”是动态库的名字。
2)编译
javacHelloWorldjava
3)生成扩展名为h的头文件javah
JNIEXPORTvoidJNICALLJava_HelloWorld_(JNIEnv,jobject);
这个h文件相当于我们在java里面的接口,这里声明了一个Java_HelloWorld_(JNIEnv,jobject)方法,然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C程序的时候所使用的方法名必须和这里的一致)。
4)编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法
代码2:
#include"jnih"
#include"HelloWorldh"
#includeotherheaders
JNIEXPORTvoidJNICALLJava_HelloWorld_(JNIEnvenv,jobjectobj)
{
printf("Helloworld!/n");
return;
}
注意代码2中的第1行,需要将jnih(该文件可以在%JAVA_HOME%/include文件夹下面找到)文件引入,因为在程序中的JNIEnv、jobject等类型都是在该头文件中定义的;另外在第2行需要将HelloWorldh头文件引入。然后保存为c就ok了。
5)生成动态库
这里以在Windows中为例,需要生成dll文件。在保存c文件夹下面,使用VC的编译器cl成。cl-I%java_home%/include-I%java_home%/include/win32-LDc-Fehellodll注意:生成的dll文件名在选项-Fe后面配置,这里是hello,因为在HelloWorldjava文件中我们loadLibary的时候使用的名字是hello。
另外需要将-I%java_home%/include-I%java_home%/include/win32参数加上,因为在第四步里面编写本地方法的时候引入了jnih文件。
JDK动态代理是基于接口使用,通过ProxynewProxyInstance方法使用。
传入参数:当前类加载器、目标接口、带目标类的InvocationHandle实现类
1、Proxy#newProxyInstance
2、Constructor#newInstance
4、sunreflectNativeConstructorAccessorImpl#newInstance
4、sunreflectNativeConstructorAccessorImpl#newInstance
ReflectionFactoryinflationThreshold 默认值是15
5、native的newInstance0
3、sunreflectDelegatingConstructorAccessorImpl#newInstance
4、执行GeneratedConstructorAccessor3代理类方法
第16次调用generate方法生成代理类GeneratesConstructorAccessor,第17次执行GeneratesConstructorAccessor代理类方法
反射类加载器会导致Perm溢出
ConstructorAccessor 有下面实现类
1、NativeConstructorAccessorImpl
JNI(java本地接口)
2、DelegatingConstructorAccessorImpl
注入ConstructorAccessorImpl属性(值是1或3),实现newInstance
3、GeneratedConstructorAccessorX
通过代理类
MethodAccessor 有下面实现类
1、NativeMethodAccessorImpl
NativeMethodAccessorImpl是通过JNI(java本地接口)存取器获取反射类字节码信息
2、DelegatingMethodAccessorImpl
DelegatingMethodAccessorImpl注入MethodAccessorImpl属性(值是1或3),实现invoke调用
3、GeneratedMethodAccessorX
通过代理类加载反射类字节码
NativeConstructorAccessorImpl或NativeMethodAccessorImpl都有一个字段numInvocations。用来计算调用JNI次数
当大于15就会生成GeneratedConstructorAccessorX或GeneratedConstructorAccessorX的字节码类文件,该字节码通过DelegatingClassLoader类加载。
为什么设计这种机制:为了提高效率
MethodAccessorGenerator类
generate方法实现了
1、asm生成字节码数组
2、defineClass生成DelegatingClassLoader代理类加载器
3、generateName方法生成字节码文件GeneratedXXXAccessorX
Inflation机制提高了反射的性能,但是对于重度使用有两个问题
1、初次加载性能较低
2、动态加载的字节码导致PermGen持续增长
JDK是基于接口实现
Inflation机制
关键是生成代理类和调用inovke方法的实现方式
1、JNI
2、asm字节码
以上就是关于如何在Android下使用JNI全部的内容,包括:如何在Android下使用JNI、如何用JNI技术提高Java的性能详解、AndroidNDK开发简介NDK和SDK以及JNI有什么关系_安卓ndk是干嘛的等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)