探索之安卓调用GO生成的动态链接库"failed: dlopen failed: could not load library "libpthread.so.0" needed by ***"的了解

如题,在安卓平台上通过JNI调用GO语言编译生成的so库。JNI部分要是做过几次的应该觉得不难吧(动、静态编译,编写规范等待)。
  原因在最后给出,可以直接拉到最后

具体的错误如下:

  • CDT build Console
08:43:38 **** Build of configuration Default for project JNIVoiceMM ****
"D:\\adt-bundle-windows-x86-20140702\\android-ndk-r10\\ndk-build.cmd" all 
Android NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 15 in ./AndroidManifest.xml    
[armeabi] Compile++ thumb: maina <= maina.cpp
[armeabi] Prebuilt       : libwebclient.so <= jni/webclient/
[armeabi] Prebuilt       : libmmain.so <= jni/mmain/
[armeabi] StaticLibrary  : libstdc++.a
[armeabi] SharedLibrary  : libmaina.so
[armeabi] Install        : libmaina.so => libs/armeabi/libmaina.so
[armeabi] Install        : libmmain.so => libs/armeabi/libmmain.so
[armeabi] Install        : libwebclient.so => libs/armeabi/libwebclient.so

08:43:45 Build Finished (took 6s.749ms)


  • LogCat信息如下
06-07 08:51:31.019: D/dalvikvm(2590): Trying to load lib /data/app-lib/com.wkw.voicemessagectrl-1/libwebclient.so 0x42466a60
06-07 08:51:31.029: E/dalvikvm(2590): dlopen("/data/app-lib/com.wkw.voicemessagectrl-1/libwebclient.so") failed: dlopen failed: could not load library "libpthread.so.0" needed by "libwebclient.so"; caused by library "libpthread.so.0" not found
06-07 08:51:31.029: W/dalvikvm(2590): Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/wkw/activity/MainActivity;
06-07 08:51:31.029: W/dalvikvm(2590): Class init failed in newInstance call (Lcom/wkw/activity/MainActivity;)
06-07 08:51:31.029: D/AndroidRuntime(2590): Shutting down VM
06-07 08:51:31.029: W/dalvikvm(2590): threadid=1: thread exiting with uncaught exception (group=0x42195ba8)
06-07 08:51:31.039: E/AndroidRuntime(2590): FATAL EXCEPTION: main
06-07 08:51:31.039: E/AndroidRuntime(2590): Process: com.wkw.voicemessagectrl, PID: 2590
06-07 08:51:31.039: E/AndroidRuntime(2590): java.lang.UnsatisfiedLinkError: dlopen failed: could not load library "libpthread.so.0" needed by "libwebclient.so"; caused by library "libpthread.so.0" not found
06-07 08:51:31.039: E/AndroidRuntime(2590):     at java.lang.Runtime.loadLibrary(Runtime.java:364)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at java.lang.System.loadLibrary(System.java:526)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at com.wkw.activity.MainActivity.(MainActivity.java:92)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at java.lang.Class.newInstanceImpl(Native Method)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at java.lang.Class.newInstance(Class.java:1208)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at android.app.Instrumentation.newActivity(Instrumentation.java:1061)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2112)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at android.app.ActivityThread.access$800(ActivityThread.java:135)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at android.os.Handler.dispatchMessage(Handler.java:102)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at android.os.Looper.loop(Looper.java:136)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at android.app.ActivityThread.main(ActivityThread.java:5017)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at java.lang.reflect.Method.invokeNative(Native Method)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at java.lang.reflect.Method.invoke(Method.java:515)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:815)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:631)
06-07 08:51:31.039: E/AndroidRuntime(2590):     at dalvik.system.NativeStart.main(Native Method)


  • 下面是JNI调用部分(MainActivity.java)
static {
//       System.loadLibrary("libpthread"); // 因为如上错误,此处尝试导入安卓库层中的libpthread.so但仍然找不到。所以注释掉了。
        System.loadLibrary("webclient"); // libwebclient.so是go语言编译生成的,提供登录服务器、上传下载文件等操作。
        System.loadLibrary("mmain");//C语言二次编译库,通过C调用GO,因为GO基于C
        System.loadLibrary("maina");//二次编译,生成我们想要的最终功能,以及实现数据类型的转换等。
    }

    public static native int jLogin(String s1, String s2, String s3); // 第三方库函数

    public static native String jUpload(String s1, String s2);

    public static native int jDownload(String s1, String s2);

    public static native void jSend();

    public static native void jWsclose();

    public static native void Recv();

...
public void postFiles(long startMili2, long endMili2, String filePath) {
        // Toast.makeText(getApplicationContext(), Mylib.sayHello(), 1).show();
        if (endMili2 - startMili2 > (long) 1000) {
            final File file = new File(filePath);
            if (file.exists() && file.length() > 0) {
                RequestParams params = new RequestParams();
                try {
                    params.put("files", file);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                if (NetworkUtil.isNetworkConnected(MainActivity.this)
                        && NetworkUtil.getNetworkType(MainActivity.this) == NETTYPE_WIFI) {
                    int returnvalue = jLogin("账户", "密码",
                            "域名");//初始化并执行登录操作,单点登录(SSO)
                    if (returnvalue == -1) {
                        Toast.makeText(getApplicationContext(), "登录失败!", 1)
                                .show();
                    } else {
                        Toast.makeText(getApplicationContext(), "登录成功!", 1)
                                .show();
                        String jstring = jUpload(filePath,
                                "http://192.168.202.1:9000/upload");//此服务器为临时的文件服务器,GO语言后台,用来测试上传。
                        if (jstring != null && !"".equals(jstring)
                                && !jstring.equalsIgnoreCase("null")
                                && !jstring.equals("-1")) {
                            Toast.makeText(getApplicationContext(),
                                    "上传成功!  " + jstring, 1).show();
                            file.delete();
                        } else {
                            Toast.makeText(getApplicationContext(),
                                    "上传失败!  " + jstring, 1).show();
                            file.delete();
                        }
                    }

                    //如下注释代码是我自己手动搭建的JAVA后台服务器,而现有服务器后台是以GO语言编写。
                    // client.post(
                    // "http://192.168.1.129:8080/UploadFiles/UploadFileServlet",
                    // params, new AsyncHttpResponseHandler() {
                    // @Override
                    // public void onSuccess(int arg0, Header[] arg1,
                    // byte[] arg2) {
                    // file.delete();
                    // Toast.makeText(getApplicationContext(),
                    // "文件上传成功!", 1).show();
                    // }
                    //
                    // @Override
                    // public void onFailure(int arg0, Header[] arg1,
                    // byte[] arg2, Throwable arg3) {
                    // file.delete();
                    // Toast.makeText(getApplicationContext(),
                    // "文件上传失败!", 1).show();
                    // }
                    // });
                } else {
                    file.delete();
                }
            }
        } else {
            File file = new File(filePath);
            if (file.exists())
                file.delete();
            Toast.makeText(getApplicationContext(), "录音时间过短!", 1).show();
        }
        if (audioFile.exists()) {
            audioFile.delete();
        }
    }

  以上就是整个JNI部分了,这里粗糙解释一下库。其实就是封装了一些操作的特定文件,它与静态链接库生成的最大不同之处在于,动态链接库的编译类似于C中的指针,当前库调用原始库中的函数(是两个.so文件,是依赖关系),而静态链接库的生成会将所有会用到的库都包含进来,类似于将所有会用到的库都打包进一个.a文件。这也是为什么运行程序时产生failed: dlopen failed: could not load library “libpthread.so.0” needed by “libwebclient.so”; caused by library “libpthread.so.0” not found的原因之一。

  在安卓系统/lib目录下我们可以找到libpthread-2.16.so、libpthread.so.0两个相关文件,但为什么还是会造成”libpthread.so.0” not found,这里介绍大家几个相关问题的网站,可以发现蜘丝马迹:
    Linux-Error loading libpthread.so on Android

    近期编译android的教训

  个人觉得可以着重看这个
    Cannot find Shared Library: libpthread.so.0

  大家可以搜索了解一下编译链部分,也可以去了解一下如何查看.so信息(windows下查看可以使用Cygwin),其实通过对比可以发现libwebclient.so和自己手动写C文件通过NDK编译出来的.so库信息字段是不同的(已经试过了,这个问题与CPU类型没关系,不管编译出ARM还是ARMV7等的.so库都无济于事)。

  得出结论:最终问题定位在了兼容性上,通过更改编译环境,使编译链与安卓兼容才得以解决。幸好老大及时出手,毕竟之前也没遇到过Go开发安卓库的情况。

你可能感兴趣的:(遇到过的安卓问题,android,JNI,GO)