JNI学习笔记(三)——HelloWorld
来源:互联网 发布:抢月饼javascript 编辑:程序博客网 时间:2024/05/19 16:32
概述
helloworld作为大多编程语言和平台的入门程序,JNI也不例外。下图展示了java程序调用JNI的例子:HelloWorld。编写这样一个程序,需要以下几个步骤,大多调用JNI的java程序也都需要有以下几个步骤:
1)创建声明了native 方法的类(HelloWorld.java)。
2)使用javac编译源文件,生成类文件(HelloWorld.class)。
3)使用javah -jni生成C头文件(HelloWorld.h)。
4)用C、C++实现native方法(HelloWorld.c、HelloWorld.cpp)。
5)在主机环境中用C、C++编译器将该实现编译生成native库文件(HelloWorld.dll、libHelloWorld.so)。
6)在java运行时中运行改程序。HelloWorld.class和(HelloWorld.dll或者libHelloWorld.so)都被导入到运行时中。
声明native方法
用java编程语言开始编写这个程序。定义一个HelloWorld类:
class HelloWorld
{
public static void main(String[] args)
{
new HelloWorld.print();
}
public native void print();
static
{
System.loadLibrary("HelloWorld");
}
}
声明native方法时,必须包含修饰字:native,同时在java编程语言中不应该实现该方法。在native方法被调用前,native库必须被导入。我们在静态初始化中导入native库。java VM将在调用HelloWorld类中的任何方法前,先自动地运行静态初始化,这样就保证了在native方法print()在native库被导入之后才被调用。
在定义的main方法中,像调用其他普通的java语言的方法一眼调用native方法。
System.loadLibrary中的参数是库的名字,库的名字是指库文件中除去前缀(linnux)和后缀的部分,如WIN32的HelloWorld.dll文件、LINUX的libHelloWorld.so文件,其库名都是HelloWorld。
编译HelloWorld类
在完成HelloWorld.java文件之后,使用javac编译器编译生成java类:
javac HelloWorld.java
这条命令会在当前目录下生成一个HelloWorld.class文件。
创建native方法的头文件
通过以下命令可以自动生成头文件:
javah -jni HelloWorld
更常用的形式是:javah -d ./OutPath -classpath ./ClassPath -jni PackageName.ClassName
在头文件HelloWorld.h中,会有一个函数声明:
JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *, jobject);
该函数的实质就是:
1)JNIEXPORT声明该接口为动态库导出接口。
2)JNICALL声明了函数参数的入栈方式。
3)函数名为包名+类名+native方法名。
例如,如果包名是com.jni.demo,类名是HelloWorld,native方法名print,则该函数名要改为:Java_com_jni_demo_HelloWorld_print。
4)函数参数,每个函数都会额外添加两个参数:JNIEnv *,jobject或者jclass(static native方法时)。具体作用以后再讲。
写native方法的实现
javah生成的JNI类型的头文件,只是帮助你用C、c++编写实现native方法。例如Java_HelloWorld_print()可以如下实现,就如你在实现其他C、C++函数一样:
#include <jni.h> /* 必须包含该头文件,它是jni的关键 */
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}
编译源文件并且创建native库
回忆一下在创建HelloWorld类的时候,有一行代码:
System.loadLibrary("HelloWorld");
必要的C、C++代码已经完成了,现在需要将它们编译成native库。不同的操作系统,用不同的方式来生成native库。
1)linux(Solaris)
cc -G -I/java/include -I/java/include/solaris HelloWorld.c -o libHelloWorld.so
-G选项,是让编译器生成一个共享库文件。
2)Win32,用Microsoft Visual C++编译生成DLL文件:
cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD HelloWorld.c -FeHelloWorld.dll
-MD选项,保证HelloWorld.dll是和Win32多线程的C库一起链接的。
-LD选项,是让编译器生成一个DLL文件。
运行该程序
此刻,我们已经有了运行该程序所必要的两个组件:native库和java class。我们可以通过以下命令来运行改程序:
java HelloWorld
我们将可以看到这样的输出:
Hello World!
在运行前,有必要为程序设置正确的native库的路径。native库的路径是一个目录的列表,java VM在导入native库的时候会搜索该列表。如果没有设置,或者没有正确的设置native库的路径,在运行时,将会看到类似于以下的错误信息:
java.lang.UnstatisfieldLinkError: no HelloWorld in library path
at java.lang.Runtime.loadLibrary(Runtime.java)
at java.lang.System.loadLibrary(System.java)
at HelloWorld.main(HelloWorld.java)
保证native库时驻留在库路径中的一个目录中。
1)如果是linux,设置该路径到环境变量LD_LIBRARY_PATH中:
LD_LIBRARY_PATH=.
export LD_LIBRARY_PATH
2)如果是Windows,则保证HelloWorld.dll是在当前目录,或者是在一个被列在PATH环境变量中的一个目录下。
3)在对于java 2 SDK1.2版本,也可以在java命令中指定native库的路径为系统的属性:
java -Djava.library.path=. HelloWorld
-D选项,设置了java平台的系统属性。设置了java.library.path的属性为“.”,只是java VM在当前目录下寻找native库。
- JNI学习笔记(三)——HelloWorld
- JNI学习笔记三
- libgdx 学习笔记三 HelloWorld
- Netty学习笔记—helloWorld
- JNI学习笔记(二)——JNI
- android jni——helloworld
- android-----JNI学习 helloworld
- android-----JNI学习 helloworld
- JNI学习(一)----helloworld
- android-----JNI学习 helloworld
- android-----JNI学习 helloworld
- android-----JNI学习 helloworld
- Android学习笔记(三)-第一个Android应用HelloWorld
- android 学习笔记(三) 第一个Android应用HelloWorld
- JNI学习(一)、JNI简介和HelloWorld示例
- Android学习笔记(1)——HelloWorld目录结构
- Hadoop学习笔记(二)——map reduce Helloworld
- Cocos2dx学习笔记(1)——认识HelloWorld
- Android中Canvas方法总结
- 两个无线路由器用网线连接
- SQL 索引视图
- 基于Iphone的一些分享-新梅传信
- C/C++/C#面试题精选(5)
- JNI学习笔记(三)——HelloWorld
- linux php安装编译模块
- Java虚拟机体系结构
- ubuntn下装mysql
- 序列化
- J2EE系统应用性能问题解决的通用方法
- 提示错误:arm-linux-gcc: Command not found
- 比较好的资源下载网站
- u-boot-2011.06 raise: Signal # 8 错误修正