今天花了至少3个小时跑这个java调c的动态链接库的Hello,native world的程序。
把所有犯的错误和要点总结一下!
1 java 中 c语言函数的声明
public native static void greeting(); //就像是接口声明一样,不过有native!
2 编译 javac HelloNative.java ,然后使用 javah
javah HelloNative会自动产生c的头文件HelloNative.h3 生成的头文件 的 第一句子为
#include <jni.h>
但是gcc里面默认环境可不知道jni.h是什么东西,
jni.h在jdk的$JAVA_HOME/include或者$JAVA_HOME/include/linux下面,可进去查看一下~
4 接下来就是根据HelloNative.h中声明的方法写C语言的实现,注意,自动生成的那个函数名字很长,并且 开头的 Java是大写的,大小写很致命,(最后我的程序在动态库已经加载好的情况下报错:java.lang.UnsatisfiedLinkError: HelloNative.greeting()V,就是因为c语言中的函数名字大小写写错,奇怪!编译不报错.....)
5 linux下编译生成动态库,注意不同环境的不一样~
gcc -fPIC -I jdk/include -I jdk/include/linux -shared -o libHelloNative.so HelloNative.c
在这里,我犯的错:
a,不理解 -I jdk -I 是include,显示指定库的库的地址,自然后面的jdk是要用你的设计地址替换的,b, 着急的去网上搜索问题,没有注意的在linux下,动态链接库的名字 必须是 lib****.so,必须以lib开头!
6 编译生成了 libHelloNative.h之后,接下写一个test类,如 HelloNativeTest,
当然要调用System.loadLibrary("HelloNative");
注意此时不要lib,也不要.so!;
调用执行 HelloNative.greeting();这个时候错误又来了:
java.lang.UnsatisfiedLinkError: no HelloNative in java.library.path。这个错误很经典,原因:是java找不到库路径~:
显然: libHelloNative.so放在当前路径 ".",
只linux执行的时候却不知道在当前路径找。 linux很“傻”很“复杂”~
a. linux下面java.library.path 和环境变脸 jdk/bin的那个个PATH不是一回事情,有另外一个默认变量 LD_LIBRARY_PATH来保存他的信息。而windows下,首先java会找当前目录,其次,它会去环境变量的地址找!
b。 由于linux的路径特殊,所以,解决方法 1-可以调用sysout(
System.getProperty("java.library.path"));来查看! 然后把 libXXXX.so拷贝到那里面的目录下去
2 设置环境变量 export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ,但是设置到哪里呢? /etc/profile ? or /root/.bashrc 不知道...忘记了linux的加载顺序了~
3 可以单次执行时候指定library位置:
java -Djava.library.path=. HelloNativeTest
总结犯错:1不知道gcc编译时候指定库 2 不了解java.libray.path的特点,特别是砸linux下 3 c语言实现函数的时候拼写错误 4 排除问题不够理性,系统化,出现了烦躁情绪,导致效率低。 时刻明白,机器只是做你指定的事情,总是你自己出错了~~~
附:gcc 参数解释(转载):
最主要的是GCC命令行的一个选项:
-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件
l -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
l -L.:表示要连接的库在当前目录中
l -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
l LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。
l 当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。
4、注意
调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。
文章来自: 好喜爱学习网(http://www.haoxiai.net) 网址:http://www.haoxiai.net/caozuoxitong/linux/5227.html
分享到:
相关推荐
本文将深入探讨这两种方法,以及如何在Java中调用C语言编写的SO(Linux下的动态链接库)和DLL(Windows下的动态链接库)中的函数。 首先,JNI是Java官方提供的原生接口,允许Java代码直接与本地代码交互。在Java中...
这将生成一个动态链接库`libnative-lib.so`。 7. **运行Java程序** 将生成的本地库与Java类一起打包成jar文件,然后在Java程序中加载这个库,就可以调用本地方法了。例如: ```java public class Main { ...
这个"linux-java调用c语言编译的so动态库-jni例子-简单计算器"是一个典型的示例,展示了如何利用JNI来创建一个Java应用程序,该程序能够调用C编写的动态链接库(.so文件)进行计算操作。 JNI是Java平台的一部分,它...
### Java如何通过JNI调用C语言 #### 一、引言 Java作为一种广泛使用的编程语言,因其具有良好的跨平台特性而备受青睐。然而,这种跨平台能力也导致Java与底层系统的交互较为有限,从而限制了某些功能的实现。为了...
通过这个实例,我们了解了如何使用Java的JNI调用C语言函数的基本步骤:声明Java本地方法、生成C语言头文件、编写C代码、编译C代码为动态链接库,最后在Java中调用该库。这种方法在需要高效计算、底层系统交互或利用...
在Java编程环境中,有时我们需要利用C语言编写的高效或特定功能的库,这时可以借助Java Native Interface (JNI) 来实现Java调用C的动态链接库。以下将详细讲解这一技术。 1. Java Native Interface (JNI) JNI是...
接下来,我们需要编译C/C++代码为动态链接库,通常为`.dll`(Windows)或`.so`(Linux)。这通常涉及到设置正确的编译选项和链接到`libjvm`库。在本例中,`coreUtil`可能是一个项目文件,包含编译和链接设置。`...
在本实例中,我们将深入探讨如何使用纯C语言通过JNI调用Java对象的方法。这个例子特别适合那些需要利用C/C++的高效性能,同时又需要与Java应用程序集成的开发者。 首先,我们需要理解JNI的基本概念。JNI提供了一套...
在标题中提到的“jna调用C语言函数库dll、so例子”,这里的"dll"是Windows系统中的动态链接库(Dynamic Link Library),"so"则是Linux和其他类Unix系统中的共享对象(Shared Object)。这两种都是C语言或其他编译...
对应于Linux .SO”指的是一个使用Java Native Interface (JNI) 技术的示例,该示例展示了如何在Java程序中调用由Visual C++ (VC) 编译生成的动态链接库(DLL) 文件,并且这个过程在Linux系统中对应的则是调用共享对象...
- 本地方法库:包含本地方法的动态链接库,通常为`.dll`(Windows)、`.so`(Linux/Unix)或`.dylib`(Mac OS X)。 2. **JNI环境设置**: - 开发工具:如Eclipse、IntelliJ IDEA等IDE提供了对JNI的支持,方便...
本篇将详细介绍如何使用JNI调用C语言来实现特定的功能。 首先,理解JNI的基本概念是关键。JNI提供了一种机制,让Java虚拟机(JVM)能够调用本地(Native)代码,也就是非Java语言编写的代码,通常是C或C++。这个...
在压缩文件`jnistb10`中,可能包含了上述步骤的示例代码,包括Java源文件、生成的头文件、C源代码和编译后的动态链接库。通过分析这些文件,你可以更深入地了解Java和C之间如何通信,以及如何在实际项目中应用JNI。 ...
根据提供的文件信息,我们可以梳理出以下知识点: ...这个过程涉及到跨语言编程、操作系统底层调用和动态链接库的管理,需要开发者对Java和C语言都有一定的了解,并熟悉Linux操作系统的环境和API。
`-I`选项指定Java头文件的位置,`-shared`标志告诉编译器创建一个动态链接库。 运行此项目,你需要先在命令行中执行`make`来编译C++代码,生成动态库。然后使用以下命令运行Java程序: ```bash java -Djava....
最终,将这些实现编译为动态链接库(native-lib),并由Java代码加载。 对于HAL(硬件抽象层),它是一组用于定义Android设备硬件功能的API和模块。HAL的目的是使Android应用程序能够以统一的方式访问硬件资源,而...
最后,我们用`gcc`生成动态链接库文件`libtoUpper.so`,并将库路径添加到环境变量`LD_LIBRARY_PATH`,这样Java就可以找到并加载这个库。 总结一下,这个JNI示例涵盖了以下知识点: 1. JNI的基本概念和作用。 2. ...
标题 "LuaJava在Android平台的动态链接库文件" 指出的是将Lua与Java集成在Android应用开发中的技术实践。Lua是一种轻量级的脚本语言,常用于游戏开发和系统配置等场景,而Java是Android应用的主要编程语言。在...
- **示例**:例如,Java应用可能需要读取硬件传感器的数据,这时可以通过JNI调用C语言编写的函数来直接与硬件交互。 2. **文件方法** - **定义**:通过创建共享文件,Java和C语言程序可以分别写入和读取数据。 -...