java.lang.NoClassDefFoundError: failed for class xxx

这个错误是在我使用第三方监控sdk展示监控视频时发生的,而且运行在Android6.0以下版本的机器上时则不会崩溃。运行时崩溃的日志如下:

java.lang.NoClassDefFoundError:  failed for class org.MediaPlayer.PlayM4.Player; see exception in other thread
    at com.gexun.kanban.main.monitor.widget.PlaySurfaceView.processRealData(PlaySurfaceView.java:121)
    at com.gexun.kanban.main.monitor.widget.PlaySurfaceView.access$000(PlaySurfaceView.java:23)
    at com.gexun.kanban.main.monitor.widget.PlaySurfaceView$1.fRealDataCallBack(PlaySurfaceView.java:105)

意思是出现了java.lang.NoClassDefFoundError这种类型的错误,而原因是执行org.MediaPlayer.PlayM4.Player这个类的方法失败导致的。

是类和接口的初始化方法。Java虚拟机动态加载、链接和初始化类和接口,而初始化时就会执行这个方法。此方法包含类变量初始化和静态初始化语句。请参考:Chapter 5. Loading, Linking, and Initializing.

于是我就去检查org.MediaPlayer.PlayM4.Player这个类,类变量初始化没什么问题,唯一比较可疑的是这个静态代码块:

    static {
        System.loadLibrary("CpuFeatures");
    }

在这个静态代码块中加载了一个本地so库,联想到错误只会出现在Android6.0及以上版本,猜测可能是这个so库比较旧,不兼容6.0及以上版本。由于没有第三方sdk不在维护,只能将项目的targetSdkVersion改为23以下,然后就运行在6.0及以上的设备上就不在报错了。

而且,有趣的是有时候运行就会直接打印出下面这个错误:

java.lang.UnsatisfiedLinkError: dlopen failed: /data/app/com.gexun.kanban-1/lib/arm/libCpuFeatures.so: has text relocations
    at java.lang.Runtime.loadLibrary(Runtime.java:372)
    at java.lang.System.loadLibrary(System.java:1076)
    at org.MediaPlayer.PlayM4.Player.(Player.java:988)
    at com.gexun.kanban.main.monitor.widget.PlaySurfaceView.processRealData(PlaySurfaceView.java:121)
    at com.gexun.kanban.main.monitor.widget.PlaySurfaceView.access$000(PlaySurfaceView.java:23)
    at com.gexun.kanban.main.monitor.widget.PlaySurfaceView$1.fRealDataCallBack(PlaySurfaceView.java:105)

即执行方法失败的具体原因。果然是在加载libCpuFeatures.so这个库时出错。

其实在官方文档中已有说明:

On previous versions of Android, if your app requested the system to load a shared library with text relocations, the system displayed a warning but still allowed the library to be loaded. Beginning in this release, the system rejects this library if your app’s target SDK version is 23 or higher. To help you detect if a library failed to load, your app should log the dlopen(3) failure, and include the problem description text that the dlerror(3) call returns. To learn more about handling text relocations, see this guide.

也就是说,Android6.0及以上的系统将会拒绝加载包含text relocations的共享库。

所以,要么你就把targetSdkVersion改为23以下,要么你就修改so库的源码重新编译(如果可能)。

你可能感兴趣的:(Android,JNI,clinit,failed,text,relocations)