23JNI与Android VM之关系.doc_第1页
23JNI与Android VM之关系.doc_第2页
23JNI与Android VM之关系.doc_第3页
23JNI与Android VM之关系.doc_第4页
23JNI与Android VM之关系.doc_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

23.JNI与AndroidVM之关系1.从如何载入*.so档案谈起由于Android的应用层级类别都是以Java撰写的,这些Java类别转译为Dex型式的Bytecode之后,必须仰赖Dalvik虚拟机器(VM:VirtualMachine)来执行之。VM在Android平台里,扮演很重要的角色。此外,在执行Java类别的过程中,如果Java类别需要与C组件沟通时,VM就会去加载C组件,然后让Java的函数顺利地呼叫到C组件的函数。此时,VM扮演着桥梁的角色,让Java与C组件能透过标准的JNI接口而相互沟通。应用层级的Java类别是在虚拟机器(VM:VitualMachine)上执行的,而C组件不是在VM上执行,那么Java程序又如何要求VM去加载(Load)所指定的C组件呢?可使用下述指令:System.loadLibrary(*.so的檔名);例如,在上一节的范例里的NativeJniAdder类别,其程序代码:看看Android框架里所提供的MediaPlayer.java类别,内含指令:publicclassMediaPlayerstaticSystem.loadLibrary(media_jni);.这要求VM去加载Android的/system/lib/libmedia_jni.so档案。载入*.so档之后,Java类别与*.so档就汇合起来,一起执行了。2.如何撰写*.so的入口函数-JNI_OnLoad()与JNI_OnUnload()函数之用途当VM执行到System.loadLibrary()函数时,首先会去执行C组件里的JNI_OnLoad()函数。它的用途有二:1.告诉VM此C组件使用那一个JNI版本。如果你的*.so文件没有提供JNI_OnLoad()函数,VM会默认该*.so檔是使用最老的JNI1.1版本。由于新版的JNI做了许多扩充,如果需要使用JNI的新版功能,例如JNI1.4的java.nio.ByteBuffer,就必须藉由JNI_OnLoad()函数来告知VM。2.由于VM执行到System.loadLibrary()函数时,就会立即先呼叫JNI_OnLoad(),所以C组件的开发者可以藉由JNI_OnLoad()来进行C组件内的初期值之设定(Initialization)。例如,在Android的/system/lib/libmedia_jni.so档案里,就提供了JNI_OnLoad()函数,其程序代码片段为:/#defineLOG_NDEBUG0#defineLOG_TAGMediaPlayer-JNIjintJNI_OnLoad(JavaVM*vm,void*reserved)JNIEnv*env=NULL;jintresult=-1;if(vm-GetEnv(void*)&env,JNI_VERSION_1_4)!=JNI_OK)LOGE(ERROR:GetEnvfailedn);gotobail;assert(env!=NULL);if(register_android_media_MediaPlayer(env)0)LOGE(ERROR:MediaPlayernativeregistrationfailedn);gotobail;if(register_android_media_MediaRecorder(env)0)LOGE(ERROR:MediaRecordernativeregistrationfailedn);gotobail;if(register_android_media_MediaScanner(env)0)LOGE(ERROR:MediaScannernativeregistrationfailedn);gotobail;if(register_android_media_MediaMetadataRetriever(env)0)LOGE(ERROR:MediaMetadataRetrievernativeregistrationfailedn);gotobail;/*success-returnvalidversionnumber*/result=JNI_VERSION_1_4;bail:returnresult;/KTHXBYE此函数回传JNI_VERSION_1_4值给VM,于是VM知道了其所使用的JNI版本了。此外,它也做了一些初期的动作(可呼叫任何本地函数),例如指令:if(register_android_media_MediaPlayer(env)GetEnv(void*)&env,JNI_VERSION_1_4)!=JNI_OK)LOGE(ERROR:GetEnvfailedn);gotobail;由于VM通常是多执行绪(Multi-threading)的执行环境。每一个执行绪在呼叫JNI_OnLoad()时,所传递进来的JNIEnv指标值都是不同的。为了配合这种多执行绪的环境,C组件开发者在撰写本地函数时,可藉由JNIEnv指标值之不同而避免执行绪的数据冲突问题,才能确保所写的本地函数能安全地在Android的多执行绪VM里安全地执行。基于这个理由,当在呼叫C组件的函数时,都会将JNIEnv指标值传递给它,如下:jintJNI_OnLoad(JavaVM*vm,void*reserved)JNIEnv*env=NULL;.if(register_android_media_MediaPlayer(env)MonitorEnter(env,obj)!=JNI_OK).查看是否已经有其它执行绪进入此对象,如果没有,此执行绪就进入该对象里执行了。还有,也可撰写下述指令:if(*env)-MonitorExit(env,obj)!=JNI_OK)查看是否此执行绪正在此对象内执行,如果是,此执行绪就会立即离开。3.registerNativeMethods()函数之用途应用层级的Java类别透过VM而呼叫到本地函数。一般是仰赖VM去寻找*.so里的本地函数。如果需要连续呼叫很多次,每次都需要寻找一遍,会多花许多时间。此时,组件开发者可以自行将本地函数向VM进行登记。例如,在Android的/system/lib/libmedia_jni.so档案里的程序代码片段如下:/#defineLOG_NDEBUG0#defineLOG_TAGMediaPlayer-JNIstaticJNINativeMethodgMethods=setDataSource,(Ljava/lang/String;)V,(void*)android_media_MediaPlayer_setDataSource,setDataSource,(Ljava/io/FileDescriptor;JJ)V,(void*)android_media_MediaPlayer_setDataSourceFD,prepare,()V,(void*)android_media_MediaPlayer_prepare,prepareAsync,()V,(void*)android_media_MediaPlayer_prepareAsync,_start,()V,(void*)android_media_MediaPlayer_start,_stop,()V,(void*)android_media_MediaPlayer_stop,getVideoWidth,()I,(void*)android_media_MediaPlayer_getVideoWidth,getVideoHeight,()I,(void*)android_media_MediaPlayer_getVideoHeight,seekTo,(I)V,(void*)android_media_MediaPlayer_seekTo,_pause,()V,(void*)android_media_MediaPlayer_pause,isPlaying,()Z,(void*)android_media_MediaPlayer_isPlaying,getCurrentPosition,()I,(void*)android_media_MediaPlayer_getCurrentPosition,getDuration,()I,(void*)android_media_MediaPlayer_getDuration,_release,()V,(void*)android_media_MediaPlayer_release,_reset,()V,(void*)android_media_MediaPlayer_reset,setAudioStreamType,(I)V,(void*)android_media_MediaPlayer_setAudioStreamType,setLooping,(Z)V,(void*)android_media_MediaPlayer_setLooping,setVolume,(FF)V,(void*)android_media_MediaPlayer_setVolume,getFrameAt,(I)Landroid/graphics/Bitmap;,(void*)android_media_MediaPlayer_getFrameAt,native_setup,(Ljava/lang/Object;)V,(void*)android_media_MediaPlayer_native_setup,native_finalize,()V,(void*)android_media_MediaPlayer_native_finalize,;staticintregister_android_media_MediaPlayer(JNIEnv*env)returnAndroidRuntime:registerNativeMethods(env,android/media/MediaPlayer,gMethods,NELEM(gMethods);./jintJNI_OnLoad(JavaVM*vm,void*reserved)if(register_android_media_MediaPlayer(env)0)LOGE(ERROR:MediaPlayernativeregistrationfailedn);gotobail;.当VM载入libmedia_jni.so档案时,就呼叫JNI_OnLoad()函数。接着,JNI_OnLoad()呼叫register_android_media_MediaPlayer()

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论