(译)Simple JNI on Ubuntu 9.04

人们可以找到很多关于Solaris和Windows中JNI的教程,而且在那些例子中C++出现得也不是那么频繁,出于这个原因,我通过两个例子来说明一下其使用。

对于下面的程序,要求你使用的SunJDK,而不是OpenJDK(在文章后面我会再次提到这点)。

第一个例子是从Java中传递一个字符串到native method中,在native method中打印个性化的Helllo World。

public class HelloWorld {
	public native void sayHi(String name);

	static {
		System.loadLibrary("nativehw");
	}

	public static void main(String[] args) {
		HelloWorld h = new HelloWorld();
		h.sayHi("Night Rider");
	}
}

 

在这里先说明一下,我们打算通过nativehw库来调用本地方法sayHi。

编译的我们类:

javac HelloWorld.java 

 

然后生成本地方法的头文件:

javah -jni HelloWorld

 

接着实现HelloWorld.h声明的方法:

(注,注意第一行的include。原文中这段代码不是很完整,为保持作者原意,故此这里我也不做相关修改)

#include 
#include "HelloWorld.h"

using namespace std;

JNIEXPORT void JNICALL Java_HelloWorld_sayHi(JNIEnv *env, jobject o, jstring s)
{
	const char *str = env->GetStringUTFChars(s, 0); cout << "Hello " << str << endl;
	env->ReleaseStringUTFChars(s, str); 
}

 

由于在C++中没有像Java那样的垃圾收集器,所以我们需要做一些清理工作。(译者注:这个是作者的建议,在本段代码中并未体现出来)

 

写好后保存为HelloWorld.cpp然后进行编译:

g++ -shared -I/usr/lib/j2sdk1.6-sun/include -I/usr/lib/j2sdk1.6-sun/include/linux HelloWorld.cpp -o libnativehw.so 

 

注意不同系统环境的include目录的路径可能会有所不同,生成前面提到的nativehw库。

我们像这样运行的例子:

java -Djava.library.path=. HelloWorld

 预期的输出结果是“Hello Night Rider”。

 

 

 

第二个例子将展示用JNI处理一些异常,同样我们先开始编写Java代码:

public class MoreStuff {
	public native double div(double x, double y) throws Exception;

	static {
		System.loadLibrary("whatever");
	}

	public static void main(String[] args) {
		MoreStuff m = new MoreStuff();
		try {
			System.out.println("7.0 / 2.0 = " + m.div(7.0, 2.0));
			System.out.println("0.0 / 0.0 = " + m.div(0.0, 0.0));
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
}

 

 编译并且生成头文件:

javac MoreStuff.java
javah -jni MoreStuff

 

实现的声明的发发的C++代码如下:

NIEXPORT jdouble JNICALL Java_MoreStuff_div (JNIEnv *env, jobject o, jdouble x, jdouble y)
{
	if(0.0 == y){
		jclass e = env->FindClass("java/lang/IllegalArgumentException");
		if (e == 0) {
			return -3.14;
		}
		env->ThrowNew(e,"Zero argument exception.");
		env->DeleteLocalRef(e);
	}
	return x/y;
}

 

 建议使用更健壮的异常处理机制来处理异常(译者注:这也是作者的建议,并未在代码中体现出来)。

 

 

g++ -shared -I/usr/lib/j2sdk1.6-sun/include -I/usr/lib/j2sdk1.6-sun/include/linux MoreStuff.cpp -o libwhatever.so

 

 这里是执行的操作和输出的结果:

java -Djava.library.path=.
MoreStuff 7.0 / 2.0 = 3.5
Zero argument exception.

 

为了让编译通过,可能需要编辑JDKHOME/include/jni.h,包括相关文件或目录(译者注:此即为上文中为何没有在代码中包含这个的原因):

#include "jni_md.h"

 或着这样:

#include "linux/jni_md.h"

 

(译者:这里我认为作者的意思是应该是运行Java例子时使之包括相关的路径,尤其要注意jni.h和jni.md.h,这两个头文件一定不能漏掉。建议在g++中添加-I标志来特别标明这几个include路径)。

这里是我安装的JDK路径的描述,虽然jni.h也是OpenJDK源码的一部分,但是我却没有在Ubuntu8.04的OpenJDK安装路径中找到它,所以这也是我强调使用SunJDK的原因。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值