转载备注地址:
1、初始化环境介绍
1.1 环境介绍
CentOS Linux release 7.3.1611 (Core) OpenJDK 1.8
1.2 环境配置
1.2.1 OpenJDK 安装
yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel
获取java home:
dirname $(readlink $(readlink $(which java)))
设置环境变量: vim /etc/profile.d/env_export.sh
在新建的文件中填写
export JAVA_HOME=上面dirname命令获取到的路径,不要jre/bin最后这段
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
1.2.2 gcc安装
yum -y install gcc
2、Java 调用 .c文件
2.1 Java测试代码
2.2 编译Java代码
1、上传代码至服务器
2、编译.class文件
3、编译.h 头文件
2.3 查看.h头文件
2.4 编写.c文件
查看自己jni.h文件和jni_md.h文件地址
jni.h 文件
jni_md.h 文件
执行: gcc -fPIC -I /usr/lib/jvm/java-1.8.0-openjdk/include -I /usr/lib/jvm/java-1.8.0-openjdk/include/linux -shared -o libJucThreadNative.so threadNew.c
导入环境变量: 动态 c库文件
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/home/thread/
执行 java com.lai.dian.JucThread
3、 .c文件回调 java
编译一个.c文件通过jni 反射调用 java
执行命令: 编译可执行文件
gcc -o threadNew threadNew.c -I /usr/lib/jvm/java-1.8.0-openjdk/include -I /usr/lib/jvm/java-1.8.0-openjdk/include/linux -L /usr/lib/jvm/java-1.8.0-openjdk/jre/lib/amd64/server -ljvm -pthread
执行文件: 编译库文件.so
gcc -fPIC -I /usr/lib/jvm/java-1.8.0-openjdk/include -I /usr/lib/jvm/java-1.8.0-openjdk/include/linux -shared -o libJucThreadNative.so threadNew.c
执行文件: 编译java文件
重新上传新的java文件,多了run方法
javac JucThread.java
步骤
Java 执行 JucThread这个类,初始化static System.loadLibrary( "JucThreadNative" );
调用Java_JucThread-start0() 这个方法,这个方法又通过jni 反射调用了run方法
4、注意事项
1、Java_com_lai_dian_JucThread_start0()方法就是你需要c程序定义的方法
2、gcc -fPIC -I /usr/lib/jvm/java-1.8.0-openjdk/include -I /usr/lib/jvm/java-1.8.0-openjdk/include/linux -shared -o libJucThreadNative.so threadNew.c 执行这个命令生成动态库的时候一定要确认下自己的OpenJdk的路径
-I /usr/lib/jvm/java-1.8.0-openjdk/include 导入 jni.h 头文件
-I /usr/lib/jvm/java-1.8.0-openjdk/include/linux 导入jni_md.h头文件
-fPIC: 选项作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code);这样一来,产生的代码中就没有绝对地址了,全部使用相对地址,所以代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的
-shared: Linux 下动态链接库(shared object file,共享对象文件)的文件后缀为.so,它是一种特殊的目标文件(object file),可以在程序运行时被加载(链接)进来。使用动态链接库的优点是:程序的可执行文件更小,便于程序的模块化以及更新,同时,有效内存的使用效率更高
-o: 生成指定文件
3、export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/home/thread/
导入动态库的环境地址
4、每次修改 threadNew.c文件 需要重新编译.so文件
5、参考地址
GCC生成动态链接库(.so文件):-shared和-fPIC选项
6、总结
1、如何调用run方法?
thread -> start -> start0 ->native --> pthread_create(第三个参数是线程主体方法){ 这里是通过jni反射调用,jvm不是这样操作的}
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
2、遗留问题jvm 如何通过hotspot c++ 方法调用java ?