[诡异bug]Android 调用so库的时候报 “dlopen failed: recursive link to xxx.so”

相关背景:

最近在封装一个jni,就是根据.h文件封装给别人的so库封装一套jni接口供java层去调用。

** 错误信息**
图片说明

已经排除的原因

  • 编译so库错误:可以参考比较奇怪的现象。已经在华为手机上运行过了。
  • so库缺少:如果少放了某个so库,提示的错误和这个不同。所以排除so库缺少的原因。
  • 平台不匹配:调试的机器为v7a,编译的so库也为v7a。所以不是平台不匹配的原因。
  • 路径错误:这个就更不可能了。

比较奇怪的现象

  • 因为调试的机器是公司定制的,所以我之前一直在这个机器上调试。有一天我放在自己的手机上(华为荣耀10)调试后,发现是可以正常运行的。

Application.mk

APP_STL := gnustl_shared
APP_PLATFORM := android-21
APP_ABI := armeabi-v7a

Android.mk

#Android.mk
LOCAL_PATH := $(call my-dir)


#e.so模块
include $(CLEAR_VARS)
LOCAL_MODULE    := e
LOCAL_SRC_FILES := armeabi-v7a/e.so
include $(PREBUILT_SHARED_LIBRARY)

#f.a模块
include $(CLEAR_VARS)
LOCAL_MODULE    := f
LOCAL_SRC_FILES := armeabi-v7a/f.a
include $(PREBUILT_STATIC_LIBRARY)

#libgnustl_shared模块
include $(CLEAR_VARS)
LOCAL_MODULE    := g
LOCAL_SRC_FILES := armeabi-v7a/libgnustl_shared.so
include $(PREBUILT_SHARED_LIBRARY)

#自己的编译模块
include $(CLEAR_VARS)
LOCAL_MODULE    := faceDetectJni
LOCAL_SRC_FILES := faceDetectJni.c
LOCAL_LDLIBS    += -L$(SYSROOT)/lib -llog

#这里引入第三方编译静态模块
LOCAL_STATIC_LIBRARIES := f
#这里引入第三方编译动态模块
LOCAL_SHARED_LIBRARIES :=e\
g
include $(BUILD_SHARED_LIBRARY)

找到一个解决办法,就是讲so库全部编译成.a库然后再封装。

动态库存在循环依赖,在 android 5.1 中会报错,新版本不会,android 底层实现有改变。

5.1 代码片段如下:

881static bool is_recursive(soinfo* si, soinfo* parent) {
882  if (parent == nullptr) {
883    return false;
884  }
885
886  if (si == parent) {
887    DL_ERR("recursive link to \"%s\"", si->name);
888    return true;
889  }
890
891  return !parent->get_parents().visit([&](soinfo* grandparent) {
892    return !is_recursive(si, grandparent);
893  });
894}