Android Studio下Ndk开发踩过的坑以及解办法决

 Android studio在2.2之后是开始兼容ndk的开发,尝鲜用来本地开发,各种坑,不兼容。之前用得好好的,一个升级AS或者NDK版本都会一不小心导致了编译失败,或者成功之后,加载不成功。故随手笔记记录下自己踩过的坑,也方便其他人查询。

     

Trap One :

     Caused by: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__aeabi_memcpy" referenced by **

 

         原因:

          情景一、AS配置Builde.grade来编译生成so文件。

          升级AS之后,到2.3版本,新建的module默认配置builde.grade中Android sdk编译版本,以及目标目标都会自动配置到最新版    本,这个时候就会容易没有注意到新版本的sdk(version>23),这是24版本之后出现的bug,但不能低于9。

        解决方式:把目标版本降低到23以及以下即可  

         详细说明:http://stackoverflow.com/questions/39541599/error-loading-package-jni-cannot-locate-symbol-aeabi-memcpy

        情景二、使用Ndk-build命令

         修改Application.mk文件中APP_PLATFORM所配置的版本要高于8以上,但不能高于23

 

Trap Two:

           NDK library "libgnustl_shared.so" not found

     这个是STL配置错误导致的,查看发现APP_STL := gnustl_shared 配置成共享型了。

     APP_STL 可用值
    stlport_static - 使用STLport作为静态库
    stlport_shared - 使用STLport 作为共享库
    gnustl_static  -  使用GNU libstdc++ 作为静态库
    gnustl_shared -  使用GNU libstdc++ 作为共享库

其中STLport和libstdc的区别详见https://www.zhihu.com/question/20845153。建议配置成stlport_static

 

 Trap Three: DeleteLocalRef error

       在jni.h中定义void DeleteLocalRef(jobject localRef)函数删除引用时,是针对尝试jobject以及子类,如jstring,jclass,jobject

 但是一些基本类型的 jboolean 、jmethodId 、jfieldId 缺不可以,否则会报编译失败。

 

Trap Three: local reference table overflow     

JNI ERROR (app bug): local reference table overflow (max=512)
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115] local reference table dump:
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]   Last 10 entries (of 512):
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       511: 0x70473f60 java.lang.Class
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       510: 0x70473f60 java.lang.Class
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       509: 0x70473f60 java.lang.Class
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       508: 0x70473f60 java.lang.Class
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       507: 0x70473f60 java.lang.Class
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       506: 0x70473f60 java.lang.Class
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       505: 0x70473f60 java.lang.Class
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       504: 0x70473f60 java.lang.Class
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       503: 0x70473f60 java.lang.Class
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       502: 0x70473f60 java.lang.Class
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]   Summary:
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         1 of cn.egame.terminal.paysdk.EgamePay$1
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         2 of dalvik.system.DexClassLoader (1 unique instances)
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]       455 of java.lang.Class (14 unique instances)
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]        39 of java.lang.String (39 unique instances)
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         1 of java.lang.Exception
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         1 of java.io.BufferedWriter
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         1 of java.io.FileInputStream
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         1 of java.security.MessageDigest$MessageDigestImpl
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         1 of java.util.TreeMap$KeySet$1
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         1 of java.util.TreeMap
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         3 of byte[] (162 elements) (3 unique instances)
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         1 of byte[] (4096 elements)
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115]         5 of java.io.File (5 unique instances)
05-19 12:53:40.563 32571-32667/com.sanguo.cdws A/art: art/runtime/indirect_reference_table.cc:115] 
05-19 12:53:40.564 32571-32667/com.sanguo.cdws A/art: art/runtime/runtime.cc:368] Runtime aborting...

 

  在android nativie开发中jni局部引用限制了512个LocalRef,如果创建了局部引用,如上述的 jclass、jstring、jobject等通过FindClass /NewString/ NewStringUTF/NewObject来产生了localRef。如果用完了(已经传递赋值了或者不再使用了),必须调用env->DeleteLocalRef来删除,否则引用计数超过512就会导致运行终止,local reference table overflow。

        同时有个不好习惯导致没有删除,习惯性直接FindClass /NewString/ NewStringUTF/NewObject来给函数直接赋值,没有直接使用引用,并删除,依然会被计数,如下代码:

           Android Studio下Ndk开发踩过的坑以及解办法决_第1张图片

       Android Studio下Ndk开发踩过的坑以及解办法决_第2张图片

   这种方式直接导致局部应用没有被回收,循环中从而超过512个。必须直接写出来,并删除:

    Android Studio下Ndk开发踩过的坑以及解办法决_第3张图片

          所以不能再偷懒了。

    

Trap four

       dynamic section has invalid link(0) sh_type: 0 (expected SHT_STRTAB)

   多见于加载so失败,上层报UnsatisfiedLinkError 异常,由于google在Android 7.0 以后对so做了更加严格的限制,对于非标准so,比如section header缺失或者dynamic table中数据项不对,会直接崩溃,对于这类问题,可以过滤linker的log查看logcat-s linker。

 ----结头表里面dynamic section 对应的sh_link字段非法,这里正常应该是字符串表,如果不是字符串表,就会报错。

 

相关错误信息:

 

xxx.so has invalid e_phnum  

-----程序头项数不对

xxx.so has no section headers   

-----结头丢失

xxx.so .dynamic section header was not found

-----动态结区丢失

xxx.so .dynamic section has invalid link(%d) sh_type: %d (expected SHT_STRTAB)  

-----结头表里面dynamic section 对应的sh_link字段非法,这里正常应该是字符串表,如果不是字符串表,就会报错。

xxx.so has invalid offset/size of .dynamic section  

-----动态结区offset 校验失败

xxx.so: has text relocations 

-----so有text 重定位section,对于targetSDK>22 会报错。

 

 

 

 Trap Five

error:only position independent executables (PIE) are supported.

 

 

PIE这个安全机制从4.1引入,但是Android L之前的系统版本并不会去检验可执行文件是否基于PIE编译出的。因此不会报错。

但是Android L已经开启验证,如果调用的可执行文件不是基于PIE方式编译的,则无法运行。解决办法非常简单,在Android.mk中加入如下flag就行。

 

LOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIE

 

Trap six

  make: *** No rule to make target

  问题在Android.mk没有配置好,之前配置多了字符

LOCAL_PATH:= $(call my-dir)

 

你可能感兴趣的:(Android,细节技巧总结,Android,Ndk开发)