Java跨语言通信之C语言
前言
java实现跨语言通信,我一直有一个疑问,就是说使用c或者c++,或者是使用python写的模型,如何才能用在java中,或者说,比如有些高级的算法,python删除的科学计算和数据预测,如何通过java传递参数,然后使用python进行数据预测,然后获取预测结果,返回到java中,然后供后台调用呢?这个流程是这样的吗?还是说这个流程本身就不正确的。
1.java调用c程序
1.编写Helloworld.java
创建 com/test 文件夹,编写Helloworld.java文件
1 | package com.test; |
2.编译java文件
进入到com/test文件夹,进行java文件编译
1 | ## 编译java |
会生成 com_test_Helloworld.h头文件
1.java 10 生成头文件(javah不是内部或外部命令)(java调用c) 使用 javac -h 代替javah命令
3.编写C代码
编写com_test_Helloworld.c,其中的 Java_com_test_Helloworld_helloword_1C 是上一步的.h生成的函数名
1 |
|
4.配置C/C++开发环境
我的开发环境是Deepin,使用了VScode进行代码编辑,为了不让开发环境报错,我进行了这一步操作。
(1) 安装完C/C++插件
(2) Ctrl+Shift+P,打开命令行,输入 C/C++,打开编辑配置
(3) 关闭重启VScode
(4)打开.vscode文件夹下的c_cpp_properties.json文件,配置includePath路径,指向JAVA_HOME的include和include/linux
1 | { |
这样就不会报找不到 jni.h 文件的错误了。
1.已解决:JNI报错:”无法打开源文件jni.h” “JNIEXPORT此声明没有存储类或类型说明符” 这是windows下的配置
2.在 Visual Code 中出现错误
无法打开 源 文件 "jni.h"
如何解决? 这是Mac配置,但是没有说怎么配置3.1.安装C/C++ for Visual Studio Code 这里说了如何配置C/C++的include目录
4.visual studio code 一直提示无法打开头文件,按提示加入includepath也无效 这里有一个快速修复的选项
5.vscode c++includepath设置无效_配置VSCode 默认设置,打开新的C工程文件夹,自动检测库文件引用以及生成符号… 全局配置
6.vscode编译运行C代码 如何编译运行c代码
如果想要使用VScode进行调试,还需要下面的步骤
(5) 生成启动文件
Ctrl+Shift+P -> Tasks: Configure Tasks… -> Create tasks.json file from templates -> Others.
1.vscode编译运行C代码
5.编译c
如果直接使用gcc进行编译的话,可能会遇到找不到 jni.h 文件的问题,需要添加 gcc 的 includepath 目录,如下增加环境变量
1 | ## 增加环境变量 |
1.修改gcc/g++默认include路径 除了默认的/usr/include, /usr/local/include等include路径外,还可以通过设置环境变量来添加系统include的路径 :export C_INCLUDE_PATH=XXXX:$C_INCLUDE_PATH
6.复制文件
将生成的.so文件放到 $JAVA_HOME/jre/lib/amd64 目录下,如果没有这个目录,那就直接放到 $JAVA_HOME/lib目录下也可以。
1.jdk12安装后没有jre,怎么办?
7.运行java程序
在com/test目录下,运行java文件,就可以了。
1 | java Helloworld.java |
可以看到,已经有结果了。
Exception in thread “main” java.lang.UnsatisfiedLinkError
这个问题我是重新进行了上面的几步操作才解决了问题,因为我在其中改变了部分的代码原因吧。
1.Java中调用c/c++语言出现Exception in thread “main” java.lang.UnsatisfiedLinkError: Test.testPrint(Ljava/lang/String;)V…错误
2.Exception in thread “main” java.lang.UnsatisfiedLinkError”
3.java.lang.UnsatisfiedLinkError解决方法汇集 这里还提到了其他的错误,比如:Java.lang.System.loadLibrary(System.java:834) 分析: 这种错误在我们使用热启动方式发布某个使用了JNI技术的Web应用时,并将调用年native方法的jar包独立部署在该应用下面,当我们的Web应用有了更新以后,在调用到该jar包封装的native方法时,会抛出该错误。(以上OS为Windows,若是Linux或Unix,应该是xxx.so报错) 这是因为Web服务器已经在第一次加载该应用时,已经load了该dll,当该应用被再次热启动时,该dll将重新被加载,于是报错。 解决方案: 一、将含有JNI调用的jar包部署在Web服务器的公用lib库中。Web应用再发布时可以不用加载; 二、jar包部署不变,在该Web中实现一个listener,监听是否第一次启动,若不是第一次启动,屏蔽掉该jar包所含dll的加载。