[b[bug小记]System.loadLibrary加载so库时报警告JNI_OnLoad returned bad version(-1)并且crash
2014-09-11 13:15
369 查看
转自:http://blog.csdn.net/shirleyxiao/article/details/38386693?reload
这次项目中的大部分代码是写在NDK层的,并通过jni相关函数封装成一个个jni函数接口。然后在java层,通过以下这样一个NDKController类封装所有jni函数接口,供其它java代码直接调用。
public class NDKController{
static{
System.loadLibrary("libnameA");
System.loadLibrary("libnameB");
System.loadLibrary("libnameC");
System.loadLibrary("NdkLibName"); //上述libnameA,libnameB, libnameC库都是被NdkLibName库用到的更底层的库
System.loadLibrary("JniLibName");
}
... ...
... ...
... ...
public native long NdkFunc1( ..., ..., ... );
public native long NdkFunc2( ..., ..., ... );
public native long NdkFunc3( ..., ..., ... );
... ...
... ...
}//class end
这种架构在以前的项目中已经用得很稳定了。这次居然在NDKController类第一次被使用的地方就crash了,伴随在logcat中的是这样的warning:
... JNI_OnLoad returned badversion(-1)in /.../.../libxxxx.so
也就是System.loadLibrary("libnameC")加载不成功。
在网上搜索相关错误,多半类似错误的原因是在Manifest中没将APP的文件读写权限打开,或者是路径不对。总之就是不能成功读取这个so文件。可是我这里很确定路径和权限是没问题的。
然后我也怀疑是不是这里的libnameC库本身的问题,或者编译版本不对之类的,但是ibnameC库是很底层的平台库,之前项目中使用都没出现过这种加载的问题。而且即使把当前项目的android版本等相关配置改成和之前项目完全一致,问题也依然存在。
搜索过程中,发现了两个很不错的链接:
1) http://my.oschina.net/wolfcs/blog/129696 这个比较详细讲了System.loadLibrary的机制,我注意到其中有一段源代码如下:
version =(*func)(gDvmJni.jniVm, NULL);
... ...
... ...
想必是这里的gDvmJni.jniVm失败返回-1。可是我没有找到gDvmJni.jniVm对应的源代码,却幸运地又看到了下面这个网页:
2)http://blog.xuite.net/free6d1823/blog/162878865-Android+JNI+debug+%E5%BF%83%E5%BE%97
最后一句“若Java不呼叫 yyyfunction, apk啟動時會出現上述錯誤”
救了我....我的错误果然也是这个原因。很感谢原作者,因为我在google论坛等各种国外网站上搜索,也没找到这种说法,还好这位同胞小哥亲身试验过这个问题。
也就是说,System.loadLibrary加载的so库,必须有被用到,不然gDvmJni.jniVm就失败返回-1,然后就会导致程序卡死。
后来查证了下,我们最新的项目代码中果然没有用到libnameC这个so库。而我只要将System.loadLibrary("libnameC")删掉,并且在NdkLibName和JniLibName库的原始工程中的Android.mk中删掉其对libnameC的依赖关系,问题就解决了。
感觉上这应该是系统函数本身的缺陷,如果报个 “加载库没被用到”的warning是合理的,但是让程序crash就很奇怪了。没什么逻辑性。算是增长了一个工程过程中的经验值吧。
///////////////////////////////////////////////////////////////////////////////////////////////////
第二篇转载贴在下面:
291Android
App
1. 出現 E/SurfaceFlinger( 126): Permission Denial: can't access SurfaceFlinger pid=1533, uid=10046
在 project 的AndroidManifest.xml 加入
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
就可執行. 出現下面這行表示通過
D/PermissionCache( 126): checking android.permission.ACCESS_SURFACE_FLINGER for uid=10046 => granted (920 us)
註: project 必須跟系統一起build.APK 要有平台簽證.
2. 宣告native 的function, 如果沒有實際被用到, 會出現如下錯誤:
E/dalvikvm( 1244): ERROR: couldn't find native method
E/dalvikvm( 1244): Requested: Lcom/example/myproject/xxxx_class;.yyyfunction:(Ljava/lang/String;)I
W/dalvikvm( 1244): JNI_OnLoad returned bad version (-1) in /system/lib/libxxxxI.so 0x41ccddb0
W/dalvikvm( 1244): Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/example/myproject/xxxx_class;
W/dalvikvm( 1244): Exception Ljava/lang/ExceptionInInitializerError; thrown while initializing Lcom/example/myproject/another_class;
D/AndroidRuntime( 1244): Shutting down VM
在上例中, 我的cpp file 有宣告
extern "C" JNIEXPORT jint JNICALL native_yyyfunction (JNIEnv *env, jobject thisObj, jstring cmd)
static JNINativeMethod gMethods[] = {
{ .... },
{ .... },
{ "yyyfunction", "(Ljava/lang/String;)I", (void*)native_yyyfunction },
{ .... },
};
但若Java 不呼叫 yyyfunction, apk 啟動時會出現上述錯誤.
////////////////////////////////////////////////////////////////////////////////////////////
这次项目中的大部分代码是写在NDK层的,并通过jni相关函数封装成一个个jni函数接口。然后在java层,通过以下这样一个NDKController类封装所有jni函数接口,供其它java代码直接调用。
public class NDKController{
static{
System.loadLibrary("libnameA");
System.loadLibrary("libnameB");
System.loadLibrary("libnameC");
System.loadLibrary("NdkLibName"); //上述libnameA,libnameB, libnameC库都是被NdkLibName库用到的更底层的库
System.loadLibrary("JniLibName");
}
... ...
... ...
... ...
public native long NdkFunc1( ..., ..., ... );
public native long NdkFunc2( ..., ..., ... );
public native long NdkFunc3( ..., ..., ... );
... ...
... ...
}//class end
这种架构在以前的项目中已经用得很稳定了。这次居然在NDKController类第一次被使用的地方就crash了,伴随在logcat中的是这样的warning:
... JNI_OnLoad returned badversion(-1)in /.../.../libxxxx.so
也就是System.loadLibrary("libnameC")加载不成功。
在网上搜索相关错误,多半类似错误的原因是在Manifest中没将APP的文件读写权限打开,或者是路径不对。总之就是不能成功读取这个so文件。可是我这里很确定路径和权限是没问题的。
然后我也怀疑是不是这里的libnameC库本身的问题,或者编译版本不对之类的,但是ibnameC库是很底层的平台库,之前项目中使用都没出现过这种加载的问题。而且即使把当前项目的android版本等相关配置改成和之前项目完全一致,问题也依然存在。
搜索过程中,发现了两个很不错的链接:
1) http://my.oschina.net/wolfcs/blog/129696 这个比较详细讲了System.loadLibrary的机制,我注意到其中有一段源代码如下:
int version;
vonLoad =dlsym(handle,
"JNI_OnLoad");
if(vonLoad == NULL)
{
ALOGD("NoJNI_OnLoad found in %s %p, skipping init",pathName, classLoader);
}
else
{
OnLoadFunc func =(OnLoadFunc)vonLoad;
Object*prevOverride = self->classLoaderOverride;
self->classLoaderOverride= classLoader;
oldStatus =dvmChangeStatus(self, THREAD_NATIVE);
if(gDvm.verboseJni){
ALOGI("[CallingJNI_OnLoad for \"%s\"]", pathName);
}
version =(*func)(gDvmJni.jniVm, NULL);
dvmChangeStatus(self,oldStatus);
self->classLoaderOverride= prevOverride;
if(version !=JNI_VERSION_1_2 && version != JNI_VERSION_1_4 && version!= JNI_VERSION_1_6)
{
ALOGW("JNI_OnLoadreturned bad version (%d) in %s %p"
, version,pathName, classLoader);
result =
false;
}
... ...
... ...
}
想必是这里的gDvmJni.jniVm失败返回-1。可是我没有找到gDvmJni.jniVm对应的源代码,却幸运地又看到了下面这个网页:
2)http://blog.xuite.net/free6d1823/blog/162878865-Android+JNI+debug+%E5%BF%83%E5%BE%97
最后一句“若Java不呼叫 yyyfunction, apk啟動時會出現上述錯誤”
救了我....我的错误果然也是这个原因。很感谢原作者,因为我在google论坛等各种国外网站上搜索,也没找到这种说法,还好这位同胞小哥亲身试验过这个问题。
也就是说,System.loadLibrary加载的so库,必须有被用到,不然gDvmJni.jniVm就失败返回-1,然后就会导致程序卡死。
后来查证了下,我们最新的项目代码中果然没有用到libnameC这个so库。而我只要将System.loadLibrary("libnameC")删掉,并且在NdkLibName和JniLibName库的原始工程中的Android.mk中删掉其对libnameC的依赖关系,问题就解决了。
感觉上这应该是系统函数本身的缺陷,如果报个 “加载库没被用到”的warning是合理的,但是让程序crash就很奇怪了。没什么逻辑性。算是增长了一个工程过程中的经验值吧。
///////////////////////////////////////////////////////////////////////////////////////////////////
第二篇转载贴在下面:
Android JNI debug 心得
291AndroidApp
1. 出現 E/SurfaceFlinger( 126): Permission Denial: can't access SurfaceFlinger pid=1533, uid=10046
在 project 的AndroidManifest.xml 加入
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
就可執行. 出現下面這行表示通過
D/PermissionCache( 126): checking android.permission.ACCESS_SURFACE_FLINGER for uid=10046 => granted (920 us)
註: project 必須跟系統一起build.APK 要有平台簽證.
2. 宣告native 的function, 如果沒有實際被用到, 會出現如下錯誤:
E/dalvikvm( 1244): ERROR: couldn't find native method
E/dalvikvm( 1244): Requested: Lcom/example/myproject/xxxx_class;.yyyfunction:(Ljava/lang/String;)I
W/dalvikvm( 1244): JNI_OnLoad returned bad version (-1) in /system/lib/libxxxxI.so 0x41ccddb0
W/dalvikvm( 1244): Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/example/myproject/xxxx_class;
W/dalvikvm( 1244): Exception Ljava/lang/ExceptionInInitializerError; thrown while initializing Lcom/example/myproject/another_class;
D/AndroidRuntime( 1244): Shutting down VM
在上例中, 我的cpp file 有宣告
extern "C" JNIEXPORT jint JNICALL native_yyyfunction (JNIEnv *env, jobject thisObj, jstring cmd)
static JNINativeMethod gMethods[] = {
{ .... },
{ .... },
{ "yyyfunction", "(Ljava/lang/String;)I", (void*)native_yyyfunction },
{ .... },
};
但若Java 不呼叫 yyyfunction, apk 啟動時會出現上述錯誤.
////////////////////////////////////////////////////////////////////////////////////////////
相关文章推荐
- [bug小记]System.loadLibrary加载so库时报警告JNI_OnLoad returned bad version(-1)并且crash
- Android源码分析实战之JNI so库加载System.loadLibrary流程分析
- JNI_OnLoad returned bad version (-1) 问题解决 proguard
- Android System.loadLibrary及JNI_OnLoad简介
- System.BadImageFormatException : 未能加载文件或程序集“Medici.PaymentRecover, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”或它的某一个依赖项。试图加载格式不正确的程序。
- 在 Android 系统中直接调用 SO文件(包含System.loadLibrary加载so的路径解释)
- System.loadLibrary()的加载类库的路径方式
- 在 Android 系统中直接调用 SO文件(包含System.loadLibrary加载so的路径解释)
- JNI 在Android中使用System.loadLibrary()
- Java基础知识JNI 在Android中使用System.loadLibrary()
- System.IO.FileLoadException: 未能加载文件或程序集“Microsoft.ReportingServices.UpgradeScripts, Version=10.0.0.0
- java jni System.loadLibrary 接口的理解
- Java基础知识JNI 在Android中使用System.loadLibrary()
- bug之java.lang.UnsupportedClassVersionError: Bad version number in .class file (unable to load class
- 在 Android 系统中直接调用 SO文件(包含System.loadLibrary加载so的路径解释)
- Java System.LoadLibrary() 能否多次加载同一个动态库?
- “System.BadImageFormatException”类型的未经处理的异常在 PurchaseDevices.Access.dll 中发生 其他信息: 未能加载文件或程序集“System.Data.SQLite, Version=1.0.66.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139”或它的某一个依赖项。试图加载格式不正确
- 在 Android 系统中直接调用 SO文件(包含System.loadLibrary加载so的路径解释)
- 关于启动eclipse 的时候,出现弹框并且提示 “failed to load the JNI shared library "...
- [.NET]System.BadImageFormat:未能加载文件或者程序集“System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”