jdk無法在樹莓派4b上運(yùn)行

一個之前在海思平臺運(yùn)行正常的jdk版本,在32位樹莓派的系統(tǒng)上面總是沒法正常運(yùn)行。運(yùn)行java時報錯

java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory

這個錯誤網(wǎng)上一堆說要設(shè)置 LD_LIBRARY_PATH 之類的狸演。但是之前在海思平臺上面也不需要設(shè)置弦聂,而且在樹莓派上面設(shè)置了也還是報錯。后來換了另外一個版本的jdk就可以運(yùn)行了倍奢。但是之前的版本為什么不行呢庶溶?

這個so庫位于 jdk1.7.0_60/lib/arm/jli 煮纵。使用ldd查看不行的版本

-bash-5.0# ldd libjli.so
        not a dynamic executable

而可以的版本

-bash-5.0# ldd libjli.so
        linux-vdso.so.1 (0xbedbe000)
        /usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so => /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so (0xb6f0d000)
        libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0xb6efa000)
        libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6dac000)
        libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0xb6d82000)
        libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0xb6d55000)
        /lib/ld-linux-armhf.so.3 (0xb6f40000)

ldd都分析不了這個動態(tài)庫的依賴關(guān)系懂鸵,之前在amd64系統(tǒng)ldd 32位i686庫的時候遇到過。但是樹莓派也都是arm32位系統(tǒng)行疏,應(yīng)該不存在32位 64位不匹配的問題按夜狻?

PS:假如ldd不好使酿联,還可以用 readelf -d xxx 來查看某個程序或者動態(tài)庫的依賴

google搜索中终息,有人提到可以用strace分析java加載時為什么報錯。于是試了一下贞让。在漫長的結(jié)果中周崭,有這么一段

openat(AT_FDCWD, "/usr/local/jdk1.7.0_60/bin/../lib/arm/jli/libjli.so", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\330\27\0\0004\0\0\0"..., 512) = 512
_llseek(3, 79528, [79528], SEEK_SET)    = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1200) = 1200
_llseek(3, 78572, [78572], SEEK_SET)    = 0
read(3, "A2\0\0\0aeabi\0\1(\0\0\0\5ARM10TDMI\0\6\3\10\1\t"..., 51) = 51
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libjli.so", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/local/ffmpeg/lib/libjli.so", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
...

很明顯,java已經(jīng)可以根據(jù)相對路徑喳张,找到 libjli.so了续镇,但是在read aeabi一段后,就把它關(guān)閉了销部,繼續(xù)從其他路徑查找可用的 libjli.so磨取。說明這個庫的aeabi有不兼容的地方(aeabi是ARM Embedded Application Binary Interface的縮寫)。繼續(xù)google柴墩,發(fā)現(xiàn)readelf可以查看一個so的aeabi信息。

-bash-5.0# readelf -A libjli.so
Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "ARM10TDMI"
  Tag_CPU_arch: v5T
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_FP_arch: VFPv2
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_enum_size: int
  Tag_ABI_HardFP_use: Deprecated
  Tag_ABI_optimization_goals: Aggressive Speed

而可以運(yùn)行的那個版本

-bash-5.0# readelf -A libjli.so
Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "6"
  Tag_CPU_arch: v6
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_FP_arch: VFPv2
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int
  Tag_ABI_HardFP_use: Deprecated
  Tag_ABI_VFP_args: VFP registers
  Tag_ABI_optimization_goals: Aggressive Speed
  Tag_CPU_unaligned_access: v6
  Tag_DIV_use: Not allowed

開始以為是Tag_CPU_name: "ARM10TDMI"這個導(dǎo)致了程序在樹莓派上面不能正常執(zhí)行凫岖。于是想辦法編譯一個相同Tag_CPU_name的執(zhí)行程序來試驗一下江咳。apt search了一下,發(fā)現(xiàn)ubuntu自帶的arm-linux gcc版本真多啊哥放,從gcc 5到gcc 8歼指,有multilib和非multilib版本之分,還有g(shù)nueabi和gnueabihf版本之分甥雕。先挑了一個低版本的
apt install gcc-5-arm-linux-gnueabi

結(jié)果發(fā)現(xiàn)踩身,無論我怎么指定-mcpu,編譯出來的Tag_CPU_name總是沒變化社露。反而是指定-march=armv6或者armv7-a挟阻,Tag_CPU_name、Tag_CPU_arch都一起變了峭弟。后面又試了一下附鸽,用樹莓派上面自己帶的gcc,編譯出來的aeabi信息為

-bash-5.0# readelf -A a.out
Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "6"
  Tag_CPU_arch: v6
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_FP_arch: VFPv2
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_rounding: Needed
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int
  Tag_ABI_VFP_args: VFP registers
  Tag_CPU_unaligned_access: v6

暫時搞不出來arm10tdmi的瞒瘸,就先不管吧坷备。在臺式機(jī)用 arm-linux-gnueabi-gcc-5 交叉編譯出來的程序,加上-march=armv6情臭,里面只包含一句printf省撑,拿到樹莓派上面赌蔑,運(yùn)行正常,但是使用ldd分析的時候會報錯“not a dynamic executable”竟秫!交叉編譯程序的aeabi和樹莓派gcc編譯出來的已經(jīng)非常接近了娃惯!

-bash-5.0# readelf -A test
Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "6"
  Tag_CPU_arch: v6
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_rounding: Needed
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int
  Tag_CPU_unaligned_access: v6
-bash-5.0# ldd test
        not a dynamic executable
-bash-5.0# ./test
0

仔細(xì)一對比,差異之處只有 Tag_ABI_VFP_args: VFP registers鸿摇。樹莓派gcc編譯出來的帶有這個石景,而交叉編譯的沒有。google一下可以知道拙吉,這個代表著不同的浮點數(shù)函數(shù)傳參規(guī)則潮孽。沒有VFP registers的,使用的是軟浮點筷黔,浮點數(shù)都是通過整形的通用寄存器進(jìn)行傳參的往史;而帶有VFP registers的,使用的是硬浮點佛舱,浮點數(shù)直接使用浮點寄存器進(jìn)行傳參椎例。
https://developer.toradex.com/knowledge-base/linux-floating-point-calling-convention-co-processor-engine

另外,使用軟浮點EABI的稱為armel请祖,使用硬浮點的EABI被稱為armhf
https://blogs.oracle.com/jtc/is-it-armhf-or-armel
https://www.cnblogs.com/hustdc/p/7224980.html

試一下在交叉編譯的時候加上-mfloat-abi=hard订歪,結(jié)果直接報錯
/usr/lib/gcc-cross/arm-linux-gnueabi/5/../../../../arm-linux-gnueabi/bin/ld: error: /tmp/ccR9XYmB.o uses VFP register arguments, test does not
/usr/lib/gcc-cross/arm-linux-gnueabi/5/../../../../arm-linux-gnueabi/bin/ld: failed to merge target specific data of file /tmp/ccR9XYmB.o

回想起來ubuntu自帶的gcc都是分gnueabi和gnueabihf的,之前裝的是gnueabi肆捕,換成gnueabihf的
apt install gcc-5-arm-linux-gnueabihf

這個編譯出來默認(rèn)是硬浮點刷晋,而且arch已經(jīng)是v7-a的了,也無法將arch改為armv6慎陵,會報錯“ sorry, unimplemented: Thumb-1 hard-float VFP ABI”眼虱。不過現(xiàn)在普遍都是Cortex-A架構(gòu)的cpu了,問題不大席纽。這套gcc編譯出來的程序在樹莓派上面既可以正常運(yùn)行捏悬,也可以被ldd識別。

不過之前的情況還是有些疑問润梯,有些程序雖然在樹莓派上面不能被ldd識別过牙,但是是可以正確執(zhí)行的。armel和armhf的兼容性情況到底是怎樣的纺铭?寫個帶浮點運(yùn)算的測試程序

#include <stdio.h>
#include <math.h>
int main()
{
        double i = 4.0f;
        printf("%f\n", sqrt(i));
        return 0;
}

用armel工具鏈編譯出來的程序抒和,居然也能運(yùn)行!只不過輸出是 4.000錯誤的結(jié)果彤蔽!這就是一個巨坑了摧莽,可以執(zhí)行,但是運(yùn)行可能是錯的顿痪。
反過來镊辕,在armel的平臺上油够,armhf的程序是不能被執(zhí)行的,直接報 not found征懈,還好石咬。

為了進(jìn)一步模擬原來jdk那種so無法加載的情況,寫了一個動態(tài)庫

int add(int a, int b)
{
        return a+b;
}

編譯成so: arm-hisiv400-linux-gcc -shared -o libtest.so 2.c

#include <stdio.h>
extern int add(int a, int b);
int main()
{
        int a=4, b=2;
        printf("%d\n", add(a, b));
        return 0;
}

編譯執(zhí)行程序:arm-hisiv400-linux-gcc -L./ -Wl,-rpath,./ 1.c -ltest -o test
在樹莓派上面一執(zhí)行卖哎,果然就報錯了

./test: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

一開始這個add我是寫成double類型的鬼悠。但后來發(fā)現(xiàn)不需要浮點,只要浮點EABI不對亏娜,就不能加載so庫焕窝。但是如果libtest.so是用armhf工具鏈編譯的,執(zhí)行程序用armel編譯维贺,還是能跑出正確的結(jié)果它掂。

重要結(jié)論:armhf上面不會阻止armel執(zhí)行程序的執(zhí)行,但是會阻止armel動態(tài)庫的加載溯泣。armel執(zhí)行程序調(diào)用armhf的動態(tài)庫虐秋,只要不涉及浮點傳參,結(jié)果還是正常的垃沦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末客给,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子肢簿,更是在濱河造成了極大的恐慌起愈,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件译仗,死亡現(xiàn)場離奇詭異,居然都是意外死亡官觅,警方通過查閱死者的電腦和手機(jī)纵菌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來休涤,“玉大人咱圆,你說我怎么就攤上這事」Π保” “怎么了序苏?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長捷凄。 經(jīng)常有香客問我忱详,道長,這世上最難降的妖魔是什么跺涤? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任匈睁,我火速辦了婚禮监透,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘航唆。我一直安慰自己胀蛮,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布糯钙。 她就那樣靜靜地躺著粪狼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪任岸。 梳的紋絲不亂的頭發(fā)上再榄,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機(jī)與錄音演闭,去河邊找鬼不跟。 笑死,一個胖子當(dāng)著我的面吹牛米碰,可吹牛的內(nèi)容都是我干的窝革。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼吕座,長吁一口氣:“原來是場噩夢啊……” “哼虐译!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吴趴,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤漆诽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后锣枝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厢拭,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年撇叁,在試婚紗的時候發(fā)現(xiàn)自己被綠了供鸠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡陨闹,死狀恐怖楞捂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情趋厉,我是刑警寧澤寨闹,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站君账,受9級特大地震影響繁堡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一帖蔓、第九天 我趴在偏房一處隱蔽的房頂上張望矮瘟。 院中可真熱鬧,春花似錦塑娇、人聲如沸澈侠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哨啃。三九已至,卻和暖如春写妥,著一層夾襖步出監(jiān)牢的瞬間拳球,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工珍特, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留祝峻,地道東北人。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓扎筒,卻偏偏與公主長得像莱找,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嗜桌,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容