You have loaded library .so which might have disabled stack guard
前言
给web同事写了so, 人家找来了,说运行java程序时报错.
报错信息如下:
[root@localhost src_linux_fedora22]# ./run_java_prj.sh run java prj begin, please wait a moment... Java HotSpot(TM) Server VM warning: You have loaded library /usr/lib/libmy_test.so which might have disabled stack guard. The VM will try to fix the stack guard now.
It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'. Exception in thread "main" java.lang.UnsatisfiedLinkError: /usr/lib/libmy_test.so: /usr/lib/libmy_test.so: wrong ELF class: ELFCLASS64 (Possible cause: architecture word width mismatch)
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
at com.my_test.<clinit>(my_test.java:30)
折腾到最后,发现是同事的虚拟机中的java环境有问题,最后重新装了oracle原版的linux_jre和open_jdk搞定。
记录一下bug的排查过程(问题的重现,定位,解决), 这是一个证明自己清白的过程:)
自己实现的组件,自己测试的时候没问题,别人用的时候有问题,这事要搞定。不管是实现的有问题,还是环境有问题,都要找出原因来,要给个说法.
实验
我做so时,有个自己搭的虚拟机debian7.5, java和C开发环境都全的,在自己的虚拟机环境,编译运行都正常。
同事的虚拟机是centos6.5final, 他自己搭的,在这个环境下有问题。他自己玩时,只有java环境。为了给他解决装C开发环境的问题,正好将克隆后的虚拟机拷贝回来了。在这个环境下可以重现这个问题。
so工程编译完,没错。
编译选项如下:
BIN = libmy_test.so
CC = g++
CFLAGS = -Wall -g -shared -z noexecstack
INC = -I. \
-I/opt/jdk1.8.0_151/include/ \
-I/opt/jdk1.8.0_151/include/linux/ \
MY_3RD_LIB = ./lib_3rd/x64/lib3rd.so.1.0.0
SHLIBS = /usr/lib/lib3rd.so.1.0.0
# LIBS = -lstdc++ -pthread -lpthread -lm -lusb -fPIC $(SHLIBS)
LIBS = -lstdc++ -pthread -lpthread -lm -fPIC
LIBPATH = -L/usr/lib/ -L/usr/local/lib/ -L./lib/
原来没有-z noexecstack选项的,根据报错提示加上
运行测试程序(C语言),证明so的功能是正常的。
这时运行java测试程序,还是有问题。
加不加-z noexecstack选项,so工程和测试工程(C语言),都是正常的。
上网查了下,其他同学遇到这个问题,都是用 execstack -c x.so, 去清掉目标so的栈检查标记,然后再运行java程序,就正常了,但是这招在我这不好使。
查看execstack版本
[root@localhost test_dbs_epass_so]# execstack --version
execstack 1.0
如果没有装execstack,就先安装execstack
yum install prelink
测试用execstack来清目标so的栈检查标记
不好使,无论是清栈检查,还是设置栈检查,java程序载入so时,还是报错
--------------------------------------------------------------------------------
execstack -c /usr/lib/libmy_test.so
[root@localhost src_linux_fedora22]# execstack -q /usr/lib/libmy_test.so
- /usr/lib/libmy_test.so
[root@localhost src_linux_fedora22]# ./run_java_prj.sh
run java prj begin, please wait a moment...
Java HotSpot(TM) Server VM warning: You have loaded library /usr/lib/libmy_test.so which might have disabled stack guard. The VM will try to fix the stack guard now.
It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'. Exception in thread "main" java.lang.UnsatisfiedLinkError: /usr/lib/libmy_test.so: /usr/lib/libmy_test.so: wrong ELF class: ELFCLASS64 (Possible cause: architecture word width mismatch)
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
at com.my_test.<clinit>(my_test.java:30)
--------------------------------------------------------------------------------
[root@localhost src_linux_fedora22]# execstack -s /usr/lib/libmy_test.so
[root@localhost src_linux_fedora22]# execstack -q /usr/lib/libmy_test.so
X /usr/lib/libmy_test.so
[root@localhost src_linux_fedora22]# ./run_java_prj.sh
run java prj begin, please wait a moment...
Java HotSpot(TM) Server VM warning: You have loaded library /usr/lib/libmy_test.so which might have disabled stack guard. The VM will try to fix the stack guard now.
It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'. Exception in thread "main" java.lang.UnsatisfiedLinkError: /usr/lib/libmy_test.so: /usr/lib/libmy_test.so: wrong ELF class: ELFCLASS64 (Possible cause: architecture word width mismatch)
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
at com.my_test.<clinit>(my_test.java:30)
重新装java环境
现在已经怀疑java环境有问题了,准备重新装一下java环境。
查看旧的java环境
[root@localhost dev]# echo $JAVA_HOME
/usr/local/java/
[root@localhost dev]# echo $JRE_HOME
[root@localhost dev]# find / -name 'jni.h'
/opt/jdk1.8.0_151/include/jni.h
看到旧的java环境在/usr/local/java/, /opt/jdk1.8.0_151/
卸载旧的java环境
直接删除java环境的文件夹 :)
rm -rf /usr/local/java
rm -rf /opt/jdk1.8.0_151
安装新java环境
https://www.java.com/en/download/linux_manual.jsp
Linux x64 RPM => jre-8u161-linux-x64.rpm
rpm -ivh ./jre-8u161-linux-x64.rpm
查看java版本
[root@localhost dbs_ukey_ePass3000]# /usr/java/jre1.8.0_161/bin/java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
这时,还没有jni环境
yum install java-1.8.0-openjdk-devel
查看jni头文件路径
[root@localhost dbs_ukey_ePass3000]# find / -name 'jni.h'
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.161-3.b14.el6_9.x86_64/include/jni.h
修改so工程中引用的jni头文件路径,重新编译so, 重新编译C测试程序, 用测试程序证明so是好的。
再运行java测试程序,调用so的功能已经正常了:)
更多推荐
所有评论(0)