Java JNI - Hello World

首先在主目录下创建需要的文件夹。java目录存放java源码及编译文件、cpp目录存放cpp源码及编译文件。

Java JNI - Hello World_第1张图片

在java目录下创建名为Hello.java的文件,内容如下:

public class Hello {
	public native String sayHello();
	
	static {
		System.loadLibrary("Hello");
	}
}
编译,并生成本地链接库至cpp目录
javac -classpath java/ java/Hello.java
javah -d cpp/ -classpath java/ Hello

Java JNI - Hello World_第2张图片


在cpp目录下创建名为Hello.cpp的文件,内容如下:

#include "Hello.h"

JNIEXPORT jstring JNICALL Java_Hello_sayHello(JNIEnv *env, jobject obj)
{
	return env->NewStringUTF("Hello world");
}
在生成共享库之前,需要将JDK下两个头文件软链接至/usr/include/,如下图:
cd /usr/include/
sudo ln -s ~/local/jdk1.6.0_37/include/jni.h
sudo ln -s ~/local/jdk1.6.0_37/include/linux/jni_md.h
ls -l | grep 'jni'

Java JNI - Hello World_第3张图片

当然,这一步是非必需的。

编译生成共享库。如果没有做上一步,则执行以下两条命令。

g++ -I/home/insongr/local/jdk1.6.0_37/include -I/home/insongr/local/jdk1.6.0_37/include/linux -fPIC -c Hello.cpp
g++ -shared -Wl,-soname,libHello.so.l -o libHello.so.1.0 Hello.o
否则,执行下面的命令即可。
g++ -fPIC -c Hello.cpp
g++ -shared -Wl,-soname,libHello.so.l -o libHello.so.1.0 Hello.o
拷贝生成的共享库为标准文件名:

最后,在java目录中创建测试类HelloJni.java,内容如下:

public class HelloJni {
    public static void main (String args[]) {
			
        Hello hello = new Hello();
        System.out.println(hello.sayHello());

    }
}
编译并运行:
javac HelloJni.java
java -Djava.library.path=/home/insongr/jni/cpp HelloJni

如果不想在命令行中加-D参数,而是在代码中动态更改java.library.path,则代码如下:

import java.lang.reflect.Field;

public class HelloJni {
    public static void main (String args[]) {
		
        try {
            System.setProperty("java.library.path", "../cpp");
		
            Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
            fieldSysPath.setAccessible(true);
            fieldSysPath.set(null, null);

            Hello hello = new Hello();
            System.out.println(hello.sayHello());
        } catch(Exception e) {
            e.printStackTrace();
        }

    }
}
编译并运行:

如果仅仅增加代码:

System.setProperty("java.library.path", "../cpp");
是没有作用的,因为java.library.path的值在第一次加载时就已经缓存了。可以通过反射机制将ClassLoader的sys_paths变量置为null,达到重新读取java.library.path的目的。

你可能感兴趣的:(Java JNI - Hello World)