当前位置: 首页 > 后端技术 > Java

NDK系列(六):说说注册JNI函数的方法和时机

时间:2023-04-02 09:43:32 Java

璇风偣璧炲叧娉紝浣犱滑鐨勬敮鎸佸鎴戞潵璇存剰涔夐噸澶с€傪煍ュぇ瀹跺ソ锛屾垜鏄皬楣忋€傛湰鏂囧凡鏀跺綍浜嶨itHub路Android-NoteBook銆傝繖閲屾湁涓€濂桝ndroid杩涢樁鎴愰暱鐭ヨ瘑浣撶郴锛屽織鍚岄亾鍚堢殑灏忎紮浼翠滑锛屽叧娉ㄥ叕浼楀彿銆愬江鏃澘銆戯紝鍔╀綘鎵撻€犳牳蹇冪珵浜夊姏銆傚墠瑷€鍦ㄤ笂涓€绡囨枃绔犱腑锛屾垜浠彁鍒颁簡娉ㄥ唽JNI鍑芥暟锛堝缓绔婮ava鍘熺敓鏂规硶涓嶫NI鍑芥暟鐨勬槧灏勫叧绯伙級鐨勬柟寮忔湁涓ょ锛氶潤鎬佹敞鍐屽拰鍔ㄦ€佹敞鍐屻€備粖澶╂垜浠氨鏉ヨ缁嗚璇磋繖涓ょ娉ㄥ唽鏂瑰紡鐨勪娇鐢ㄦ柟娉曞拰瀹炵幇鍘熺悊銆傛湰鏂囨槸NDK绯诲垪鐨勭6绡囨枃绔犮€傛爮鐩垪琛細1.璇█鍩虹锛?.NDK瀛︿範璺嚎锛氬浣曞涔?鎴戠殑蹇冨緱2.C璇█鍩虹3.C++璇█鍩虹4.C/C++缂栬瘧杩囩▼锛氫粠婧愮爜鍒扮▼搴忚繍琛?.NDK寮€鍙戯細1.JNI鍩虹锛欽ava涓嶯ative浜や簰2.娉ㄥ唽JNI鍑芥暟锛氶潤鎬佹敞鍐?鍔ㄦ€佹敞鍐岋紙鏈枃锛?.NDK鍩虹锛歯dk-build&CMake4銆俿o鏂囦欢鍔犺浇杩囩▼鍒嗘瀽锛氫簡瑙ndroid涓璴oadLibrary()鐨勬墽琛岃繃绋?.so鏂囦欢閫傞厤64浣嶆灦鏋勶細Gradle鎻掍欢涓€閿绱㈡湭閫傞厤椤?.鍔ㄦ€乻o鏂囦欢锛氬姩鎬佷笅杞?.so鏂囦欢浣撶Н浼樺寲锛氭枃浠剁簿绠€3銆佸熀纭€鐞嗚1銆佽棰戝熀纭€鐞嗚2銆侀煶棰戝熀纭€鐞嗚3銆丠.264瑙嗛鍘嬬缉缂栫爜4銆侀煶棰戝帇缂╃紪鐮?銆丗FMPEG鍩虹6銆丱PENSLES鍩虹7銆丳NG鍥剧墖锛氭棤鎹熷帇缂╃紪鐮?銆佽绠楁満鍩虹1銆佸瓧绗︾紪鐮侊細ASCII銆乁nicode銆乁TF-8銆乁TF-16銆乁TF-321銆傞潤鎬佹敞鍐孞NI鍑芥暟1.1闈欐€佹敞鍐屼娇鐢ㄦ柟娉曢潤鎬佹敞鍐岄噰鐢ㄥ熀浜庘€滅害瀹氣€濈殑鍛藉悕瑙勫垯锛屽彲浠ラ€氳繃javah鑷姩鐢熸垚native鏂规硶瀵瑰簲鐨勫嚱鏁板0鏄庯紙IDE浼氭櫤鑳界敓鎴愶紝鏃犻渶鎵嬪姩鎵ц鍛戒护).渚嬪锛欻elloWorld.javapackagecom.xurui.hellojni锛沺ublicclassHelloWorld{publicnativevoidsayHi();}鎵ц鍛戒护锛歫avac-h銆侶elloWorld.java锛堢粨鍚堜簡javac鍜宩avah锛夛紝瀵瑰簲鐨凧NI鍑芥暟锛歝om_xurui_hellojni_HelloWorld.h銆?.JNIEXPORTvoidJNICALLJava_com_xurui_hellojni_HelloWorld_sayHi(JNIEnv*,jobject);...闈欐€佹敞鍐岀殑鍛藉悕瑙勫垯鍒嗕负鈥滄棤閲嶈浇鈥濆拰鈥滄湁閲嶈浇鈥濅袱绉嶆儏鍐碉細娌℃湁閲嶈浇鏃讹紝鈥滅煭鍚嶁€濊鍒欒閲囩敤锛屽苟涓攚ith閲嶈浇鏃跺簲鐢ㄢ€滈暱鍚嶇О鈥濊鍒欍€係hortnamerule锛堢畝绉帮級锛欽ava_[绫荤殑鍏ㄩ檺瀹氬悕锛堝甫涓嬪垝绾匡級]_[鏂规硶鍚峕锛屽叾涓?鍦ㄧ被鐨勫畬鍏ㄩ檺瀹氬悕绉颁腑鏇存敼涓篲锛沴ongnamerule锛堥暱鍚嶏級锛氬湪shortname涓紝鍦╞ase鍚庨潰杩藉姞涓や釜涓嬪垝绾匡紙__锛夊拰鍙傛暟鎻忚堪绗︼紝浠ュ尯鍒嚱鏁伴噸杞姐€傝繖閲岃В閲婁竴涓嬩负浠€涔堟湁閲嶈浇鏃舵嫾鎺ュ弬鏁版弿杩扮鐨勬柟娉曪紵鍥犱负C璇█娌℃湁鍑芥暟閲嶈浇锛屾墍浠ユ棤娉曟牴鎹弬鏁版潵鍖哄垎鍑芥暟閲嶈浇锛屾墍浠ラ渶瑕佹嫾鎺ュ悗缂€鏉ユ秷闄ら噸杞姐€?.2闈欐€佹敞鍐屽師鐞嗗垎鏋愪笅闈㈠垎鏋愪竴涓嬮潤鎬佹敞鍐屽尮閰岼NI鍑芥暟鐨勬墽琛岃繃绋嬨€傜敱浜庢病鏈夋壘鍒扮洿鎺ョ浉鍏崇殑璧勬枡鍜屽嚱鏁拌皟鐢ㄥ叆鍙o紝浜庢槸浠oadLibrary()涓虹嚎绱㈠垎鏋愪簡鍔犺浇so搴撶殑鎵ц杩囩▼锛屾渶缁堝畾浣嶅埌FindNativeMethod()鏂规硶锛屼粠鍐呭涓婄湅搴旇鏄纭殑銆俲ava_vm_ext.cc//鍏变韩搴撳垪琛╯td::unique_ptrlibraries_;//鎼滅储JNI鍑芥暟瀵瑰簲鐨勫師鐢熷嚱鏁版寚閽坴oid*FindNativeMethod(Thread*self,ArtMethod*m,std::string&detail){//1.鑾峰彇鏈湴鏂规硶瀵瑰簲鐨勭煭鍚嶇О鍜岄暱鍚嶇Оstd::stringjni_short_name(m->JniShortName());std::stringjni_long_name(m->JniLongName());//2.鍦ㄥ姞杞界殑so搴撲腑鏌ユ壘void*native_code=FindNativeMethodInternal(self,declaring_class_loader_allocator,shorty,jni_short_name,jni_long_name);returnnative_code;}//2.鍦ㄥ姞杞界殑so搴撲腑鏌ユ壘void*FindNativeMethodInternal(Thread*self,void*declaring_class_loader_allocator,chartor*,constconststd::string&jni_short_name,conststd::string&jni_long_name){for(constauto&lib:libraries_){SharedLibrary*constlibrary=lib.second;//2.1妫€鏌ユ槸鍚︽槸鍚屼竴涓狢lassLoaderif(library->GetClassLoaderAllocator()!=declaring_class_loader_allocator){continue;}//2.2棣栧厛鎼滅储绠€绉癱onstchar*arg_shorty=library->NeedsNativeBridge()?鐭釜瀛愶細nullptr锛泇oid*fn=dlsym(library,jni_short_name)//2.3鐒跺悗鎼滅储闀垮悕if(fn==nullptr){fn=dlsym(library,jni_long_name)}if(fn!=nullptr){returnfn;}}returnnullptr;}art_method.cc//1.鑾峰彇nativemethod瀵瑰簲鐨剆hortname鍜宭ongname//shortnamestd::stringArtMethod:::JniShortName(){returnGetJniShortName(GetDeclaringClassDescriptor(),GetName());}//闀垮悕绉皊td::stringArtMethod::JniLongName(){std::stringlong_name;long_name+=JniShortName();long_name+="__";std::string绛惧悕锛圙etSignature().ToString());signature.erase(0,1);signature.erase(signature.begin()+signature.find(')'),signature.end());long_name+=MangleForJni(绛惧悕);杩斿洖闀垮悕锛泒descriptors_names.ccstd::stringGetJniShortName(conststd::string&class_descriptor,conststd::string&method){//杩欓噷鏄煭鍚嶇О鐨勮绠楅€昏緫}涓婇潰鐨勪唬鐮佸凡缁忓緢绠€鍖栦簡锛屼富瑕佹祦绋嬪涓?1.Calculation鏈湴鏂规硶鐨勭煭鍚嶇О鍜岄暱鍚嶇О锛?.纭畾瀹氫箟native鏂规硶绫荤殑绫诲姞杞藉櫒锛屽湪鍔犺浇鐨剆o搴搇ibraries_涓煡鎵綣NI鍑芥暟銆傚鏋滄病鏈夋彁鍓嶅姞杞絪o搴擄紝鑷劧鎵句笉鍒帮紝浼氭姏鍑篣nsatisfiedLinkError寮傚父锛?.寤虹珛鍐呴儴鏁版嵁缁撴瀯锛屽缓绔婮ava鍘熺敓鏂规硶涓嶫NI鍑芥暟鐨勫嚱鏁版寚閽堢殑鏄犲皠鍏崇郴锛?銆佸悗缁皟鐢╪ative鏂规硶锛岀洿鎺ヨ皟鐢ㄨ褰曠殑鍑芥暟鎸囬拡銆傚姞杞絪o搴撶殑杩囩▼鍦?.so鏂囦欢鍔犺浇杩囩▼鍒嗘瀽涓湁鎻愬埌銆傚姞杞界殑鍏变韩搴撳瓨鍌ㄥ湪libraries_琛ㄤ腑銆?銆佸姩鎬佹敞鍐孞NI鍑芥暟闈欐€佹敞鍐屾槸鍦ㄧ涓€娆¤皟鐢↗avanative鏂规硶鏃舵悳绱㈠搴旂殑JNI鍑芥暟锛岃€屽姩鎬佹敞鍐屾槸浜嬪厛鎵嬪姩寤虹珛鏄犲皠鍏崇郴锛屼笉闇€瑕佽窡鍦ㄩ潤鎬佹敞鍐屼箣鍚嶫NI鍑芥暟鍛藉悕瑙勫垯銆?.1鍔ㄦ€佹敞鍐屾柟娉曞姩鎬佹敞鍐岄渶瑕佺敤鍒癛egisterNatives(...)鍑芥暟锛屽湪jni.h鏂囦欢涓畾涔夛細jni.hstructJNINativeInterface{//Register//鍙傛暟2锛欽avaClass瀵硅薄琛ㄧず//鍙傛暟3锛欽NINativeMethod缁撴瀯鏁扮粍//鍙傛暟鍥涳細JNINativeMethod缁撴瀯鏁扮粍闀垮害jint(*RegisterNatives)(JNIEnv*,jclass,constJNINativeMethod*,jint);//娉ㄩ攢//鍙傛暟浜岋細JavaClass瀵硅薄琛ㄧずjint(*UnregisterNatives)(JNIEnv*,jclass);};typedefstruct{constchar*name;//Java鏂规硶鍚峜onstchar*signature;//Java鏂规硶鎻忚堪绗oid*fnPtr;//JNI鍑芥暟鎸囬拡}JNINativeMethod;绀轰緥绋嬪簭//闇€瑕佹敞鍐岀殑Java灞傜被鍚?defineJNIREG_CLASS"com/xurui/MainActivity"//JNINativeMethod缁撴瀯浣撴暟缁剆taticJNINativeMethodgmethod[]={{"onStart","()I",(void*)onStart},//JNINativeMethodstructure};//鍥炶皟JNIEXPORTjintJNICALLJNI_OnLoad(JavaVM*vm,void*reserved){JNIEnv*env=NULL;jint缁撴灉=-1;濡傛灉(vm->GetEnv((void**)&env,JNI_VERSION_1_6)!=JNI_OK){杩斿洖-1锛泒鏂█锛堢幆澧冿紒=NULL锛夛紱//鎵ц鍔ㄦ€佹敞鍐宨f(!registerNatives(env)){return-1;}缁撴灉=JNI_VERSION_1_6;returnresult;}//鍔ㄦ€佹敞鍐宻taticintregisterNatives(JNIEnv*env){//璋冪敤宸ュ叿鏂规硶瀹屾垚娉ㄥ唽if(!registerNativeMethods(env,JNIREG_CLASS,gmethod,sizeof(gmethod)/sizeof(gmethod[0])))杩斿洖JNI_FALSE锛?/JNINativeMethod缁撴瀯鏁扮粍JNINativeMethodmethods[]={{"onStop","()V",(void*)onStop},//JNINativeMethod缁撴瀯};//璋冪敤宸ュ叿鏂规硶瀹屾垚娉ㄥ唽if(!registerNativeMethods(env,JNIREG_CLASS,smethod,sizeof(smethod)/sizeof(smethod[0])))returnJNI_FALSE;returnJNI_TRUE;}//涓€涓伐鍏锋柟娉晄taticintregisterNativeMethods(JNIEnv*env,constchar*className,JNINativeMethod*gmethod,intnumMethods){//鏍规嵁绫诲悕鑾峰彇jclass瀵硅薄jclassclazz=env->FindClass(className);濡傛灉锛坈lazz==NULL锛墈杩斿洖JNI_FALSE锛泒//濡傛灉(env->RegisterNatives(clazz,gmethod,numMethods)<0){returnJNI_FALSE;}returnJNI_TRUE;}浠g爜骞朵笉澶嶆潅锛岀畝鍗曡鏄庝竴涓嬶細1銆乺egisterNativeMethods鍙槸涓€涓伐鍏峰嚱鏁帮紝绠€鍖栦簡FindClass杩欎竴姝ワ紱2.methods鏄竴涓狫NINativeMethod缁撴瀯浣撴暟缁勶紝瀹氫箟浜咼ava鍘熺敓鏂规硶涓嶫NI鍑芥暟鐨勬槧灏勫叧绯伙紝闇€瑕佽褰旿ava鏂规硶鍚嶃€丣ava鏂规硶鎻忚堪绗︺€丣NI鍑芥暟鎸囬拡锛?銆丷egisterNatives鍑芥暟鏄渶缁堢殑娉ㄥ唽鍑芥暟锛岄渶瑕佷紶閫抝class鍜孞NINativeMethod缁撴瀯浣撴暟缁?.2鍔ㄦ€佹敞鍐屽師鐞嗗垎鏋怰egisterNatives鏂规硶鐨勬湰璐ㄦ槸鐩存帴閫氳繃缁撴瀯浣撴寚瀹氭槧灏勫叧绯伙紝鑰屼笉鏄幓瀵绘壘JNI鍑芥暟璋冪敤native鏂规硶鏃剁殑鎸囬拡锛屾墍浠ュ姩鎬佹敞鍐岀殑native鏂规硶鐨勮皟鐢ㄦ晥鐜囨洿楂樸€傚彟澶栵紝鍙互鍑忓皯鐢熸垚鐨剆o搴撴枃浠朵腑瀵煎嚭绗﹀彿鐨勬暟閲忥紝浼樺寲so搴撴枃浠剁殑浣撶Н銆傝瑙丄ndroid瀵筍o澶у皬浼樺寲鐨勬帰绱笌瀹炶返涓殑鈥滅畝鍖栧姩鎬佺鍙疯〃鈥濅竴绔犮€備笁銆佹敞鍐孞NI鍑芥暟鐨勬椂鏈烘€荤粨涓€涓嬫敞鍐孞NI鍑芥暟鐨勬椂鏈猴紝涓昏鍒嗕负涓夌锛氭敞鍐屾椂鏈哄拰娉ㄥ唽鏂规硶璇存槑1.绗竴娆¤皟鐢╪ative鏂规硶鏃讹紝闈欐€佹敞鍐岃櫄鎷熸満鎼滅储JNI鍑芥暟搴撲腑鐨勫嚱鏁版寚閽堝苟璁板綍涓嬫潵锛屽悗缁皟鐢ㄤ笉闇€瑕侀噸澶嶆煡鎵?銆佸姞杞絪o搴撴椂锛屽姩鎬佹敞鍐屼細鍦ㄥ姞杞絪o搴撴椂鑷姩鍥炶皟JNI_OnLoad鍑芥暟锛屽湪鍏朵腑璋冪敤RegisterNatives娉ㄥ唽銆?.鎻愬墠娉ㄥ唽銆傚姩鎬佹敞鍐屽姞杞絪o搴撳悗锛屽湪璋冪敤native鏂规硶涔嬪墠锛岀敱闈欐€佹敞鍐岀殑native鍑芥暟瑙﹀彂RegisterNatives娉ㄥ唽銆傛瘮濡傚簲鐢ㄥ惎鍔ㄦ椂锛屼細鎻愬墠娉ㄥ唽寰堝绯荤粺婧愪唬鐮併€備互Android铏氭嫙鏈烘簮鐮佷负渚嬶細鍦╝pp杩涚▼鍚姩杩囩▼涓紝鍒涘缓铏氭嫙鏈哄悗浼氳繘琛屼竴娆NI鍑芥暟娉ㄥ唽銆傛垜浠湪寰堝Framework婧愮爜涓兘鑳界湅鍒皀ativemethods锛屼絾鏄壘涓嶅埌璋冪敤System.loadLibrary(...)鐨勫湴鏂癸紝鍥犱负鍦ㄨ櫄鎷熸満鍚姩鐨勬椂鍊欏氨宸茬粡娉ㄥ唽杩囦簡銆侫ndroidRuntime.cppvoidAndroidRuntime::start(constchar*className,constVector&options,boolzygote){...if(startReg(env)<0){ALOGE("鏃犳硶娉ㄥ唽鎵€鏈塧ndroidnatives\\n");}...}//寮€濮?>startReg:intAndroidRuntime::startReg(JNIEnv*env){androidSetCreateThreadFunc((android_create_thread_fn)javaCreateThreadEtc);env->PushLocalFrame(200);//鎵цJNI娉ㄥ唽if(register_jni_procs(gRegJNI,NELEM(gRegJNI),env)<0){env->PopLocalFrame(NULL);杩斿洖-1锛泒env->PopLocalFrame(NULL);return0;}//startReg->register_jni_procs:staticintregister_jni_procs(constRegJNIRecarray[],size_tcount,JNIEnv*env){//閬嶅巻浜岀淮鏁扮粍for(size_ti=0;i