我正在尝试通过loadLibrary
调用在我的Android应用中加载两个共享库:
System.loadLibrary("mywrapper");
System.loadLibrary("crypto");
我一直在追赶'UnsatisfiedLinkError'。这是错误的更详细版本。
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1969]:
130 could not load needed library 'libcrypto.so.1.0.0' for
'libmywrapper.so' (load_library[1111]: Library 'libcrypto.so.1.0.0' not found)
有什么想法吗?
花了一些时间后,我发现Android不支持版本化库。有没有人面临同样的问题?
答案 0 :(得分:4)
我在为Android构建libwebsockets时遇到了同样的问题,需要与OpenSSL链接。我以libssl.so为例。您应该对相关的.so文件执行相同的操作。
Before:
huiying@huiying-PORTEGE-R835:~$ objdump -p libssl.so | grep so
libssl.so: file format elf32-little
NEEDED libcrypto.so.1.0.0
NEEDED libdl.so
NEEDED libc.so
SONAME libssl.so.1.0.0
After
huiying@huiying-PORTEGE-R835:~$ rpl -R -e .so.1.0.0 "_1_0_0.so" libssl.so
Replacing ".so.1.0.0" with "_1_0_0.so" (case sensitive) (partial words matched)
.
A Total of 2 matches replaced in 1 file searched.
huiying@huiying-PORTEGE-R835:~$ objdump -p libssl.so | grep so
libssl.so: file format elf32-little
NEEDED libcrypto_1_0_0.so
NEEDED libdl.so
NEEDED libc.so
SONAME libssl_1_0_0.so
And don't forget to change file name "libssl.so" to "libssl_1_0_0.so".

黑客行事。我已经运行Android应用来证明这一点。在http://computervisionandjava.blogspot.com/2015/05/trouble-with-versioned-shared-libraries.html看到我的咆哮。
答案 1 :(得分:2)
似乎android在加载版本化库方面存在问题。手头的问题是因为我的案例libcrypto.so.1.0.0中的库名。即使您重命名库并尝试将其作为预先构建的共享库加载到android make文件中,它也会失败。(必须是因为库名以某种方式嵌入到文件中。并且任何与其链接的库都希望是与具有相同名称的库相关联)
我希望在Android中处理带有版本名称的库时还有其他方法。
现在我通过使用openssl的静态库并将它们与我自己的共享库链接来一起回避问题。
答案 2 :(得分:2)
2014年,仍然不支持版本化共享库。所以我制作了一个修补SONAME的脚本。只需将脚本指向输入所有版本化库所放置的目录即可。然后检查输出目录" unver"。
#!/bin/bash
DIR="$1"
if [ "$DIR" == "" ]; then
echo "Usage: fix-soname.sh <target dir>"
exit
fi
if [ ! -d $DIR ]; then
echo "Not found: $DIR"
exit
fi
OUT="$DIR/unver"
echo "Input=$DIR"
echo "Output=$OUT"
CWD=$(pwd)
cd $DIR
# prep dirs
mkdir -p $OUT
rm -f -R $OUT/*
# rename libs and copy to out dir
find "$DIR" -type f -name '*.so*' | while read FILE; do
NAME=$(basename "$FILE")
SONAME=$NAME
while read SYMLINK; do
X=$(basename "$SYMLINK")
#echo "$X (${#X}) -> $NAME (${#NAME})"
if [ "${#X}" -lt "${#SONAME}" ]; then
SONAME=$X
fi
done<<EOT
`find -L $DIR -samefile $FILE`
EOT
#echo $SONAME
cp -f $SONAME $OUT/
done
# patch libs in out dir
find "$OUT" -type f -name '*.so*' | while read FILE; do
# get file name without path
NAME=$(basename "$FILE")
# extract SONAME from shared lib
SONAME=`readelf -d $FILE | grep '(SONAME)' | grep -P '(?<=\[)(lib.*?)(?=\])' -o`
#echo "$NAME [$SONAME]"
# patch SONAME if required
if [ "$NAME" != "$SONAME" ]; then
L1=${#NAME}
L2=${#SONAME}
LDIFF=$((L2-L1))
#echo "$NAME [$SONAME] ($LDIFF)"
if [ "$LDIFF" -gt "0" ]; then
SONEW=$NAME
for (( c=1; c<=$LDIFF; c++ )); do
SONEW+="\x00"
done
echo "$NAME [$SONAME] -> $SONEW ($LDIFF)"
rpl -R -e "$SONAME" "$SONEW" $OUT
fi
fi
done
cd $CWD