1 首先创建一个简单的java类:
public class Hello
{
static
{
try
{
//此处即为本地方法所在链接库名
System.loadLibrary("hello");
}
catch(UnsatisfiedLinkError e)
{
System.err.println( "Cannot load hello library:\n " +
e.toString() );
}
}
public Hello()
{
}
//声明的本地方法
public native void SayHello(String strName);
}
这里有个地方要注意,就是 这个类最好不要加包信息。因为类在某个包下面,使用javah命令生成*.h头文件的时候会不一样,比如在test包下,就会生成test_Hello.h,而且 在jni调用的时候,也有区别,为了方便起见,我们这里就不加包了,免得麻烦,:)
然后,编译得到Hello.class
2 生成 Hello.h
使用命令:javah Hello
这里有一点要注意,如果这个命令报错,有可能是因为你没有当前路径到设置环境变量classpath中,所以:
javah -classpath"." Hello.class
这样写就OK了, 后面也许还会碰到类似的环境变量问题。
3 在与Hello.h相同的路径下创建一个CPP文件Hello.cpp。内容如下:
#include "Hello.h" JNIEXPORT void JNICALL Java_Hello_SayHello (JNIEnv * env, jobject arg, jstring instring) { const char *str = env->GetStringUTFChars( instring, JNI_FALSE ); printf("Hello,%s\n",str); env->ReleaseStringUTFChars( instring, str ); return; }
这个Hello.cpp 的代码,跟IBM的例子略有不同,详细原因 大家自己去查查jni.h
4.编译生成共享库
a. 编译命令,生成Hello.o
g++ -I /usr/lib/jvm/java-6-sun-1.6.0.03/include -I /usr/lib/jvm/java-6-sun-1.6.0.03/include/linux -fPIC -c Hello.cpp
b.生成动态库文件,libhello.so.1.0
g++ -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 Hello.o
这里的2个命令也跟IBM文章的例子有所不同。因为使用gcc编译得到动态库,在jni调用的时候,某些情况会有异常,所以这里改用g++。
接下来将生成的共享库拷贝为标准文件名
cp libhello.so.1.0 libhello.so
最后通知动态链接程序此共享文件的路径。
export LD_LIBRARY_PATH='pwd':$LD_LIBRARY_PATH
这里用
export 加入共享文件的路径,有时候会有点问题,比如:环境变量不会马上更新等等。
还有一个办法,就是直接将libhello.so拷贝到 /usr/lib 或者/lib 等系统库目录下
5.编写一个简单的Java程序来测试我们的本地方法。
将如下源码存为ToSay.java:
import Hello; import java.util.*; public class ToSay { public static void main(String argv[]) { ToSay say = new ToSay(); } public ToSay() { Hello h = new Hello(); //调用本地方法向John问好 h.SayHello("John"); } } 用javac编译ToSay.java,生成ToSay.class 向执行普通Java程序一样使用java ToSay,我们会看到在屏幕上出现Hello,John。 6 以下是IBM的文章中的建议:
|