JNI初步

    我们知道,java平台是个环境:该环境包含java虚拟机以及java应用程序接口,java应用程序使用java语言编写,然后编译成机器依赖型的二进制类格式,这个类可以在任何虚拟机上实现执行,当然jiava平台的实现必须保证能够支持java程序语言、虚拟机以及API。

     主机环境代表着主操作系统,包含一系列的本地库以及CPU指令等等。毋庸置疑,本地应用程序使用本地化语言进行编写,例如C,C++,然后编译成机器指定的二进制代码,然后连接到本地库。本地应用程序以及本地库通常是高度依赖特定的主机环境系统的。例如:某个C程序只能在某一类型的OS上跑起来,在其它的OS上市是没法跑通的。

    java 平台通常在主机平台依赖之上,例如:JRE(Java Runtime Environment)可以在windows,solaris,linux平台上来支持java平台的运行-----一句话,java语言的跨平台的。

   那么前面说了那么多,和JNI有啥关系吗?

    我们来看:当java程序需要访问某些本地依赖性的资源的时候怎么办?这些本地资源通常是C,C++语言进行编写的,java语言本身是没办法的了。那么这个时候JNI就起到作用了。JNI(java native interface)提供了java和本地语言程序的一个接口。使得我们在java语言中可以方便的使用C/C++语言来进行coding,利用本地已经实现的C/C++语言型的功能。提高效率。

    JNI主要提供两个功能:

    1. 你可以使用JNI来允许java应用程序能够调用用编写本地化的语言编写的本地库(WINDOWS 下是dll库,linux下是.SO文件)。

    2.JNI支持一个调用接口,该接口来允许你嵌入到java虚拟机中来实现本地化得程序:在虚拟机中实现的本地应用程序,可以和本地库链接起来,然后使用调用接口去执行用java语言实现的软件组件。例如:一个用c实现的 web 浏览器可以执行嵌入到java虚拟机中实现的一个用于下载功能applet。

    当然,JNI也不是绝对完美的,使用JNI也会失去两个好处:

   1. 平台无关性遭到破坏,用于使用了本地库的相关实现,而本地库是和OS平台紧密相关的,这样在移植的时候就不得不考虑平台问题了。

   2.java语言是类型安全型的语言,但是C/C++可不是,两个混在一起肯定是不安全型的了。所以在使用JNI的时候得小心翼翼的,一个实现不好的本地化方法极有可能造成整个程序的崩溃。由于这一点,java应用程序应该在调用JNI接口的时候进行安全型检查。

    什么时候使用JNI呢?

     一般情况下是不推荐的,因为由于上面所提到的两个弊端。尽管如此,有些情况下还是需要使用JNI的,比如:

    java程序通过TCP/IP连接或者进程间通信与本地应用程序通信。

    java程序通过JDBCTM 的API来与传统数据库进行连接。

   java 应用程序利用JAVA IDL API 中的分布式对象技术的好处来实现自己的某些功能。

  上面几种情况,一般是运行在不同的进程中的,就算一个出了问题,另一个也不会出现崩溃。这个就是进程间的地址空间独立的好处,但是,如果要求相应两个部分运行在同一个进程中呢?这种情况下其实JNI就很有用了。比如说你想访问一个本地库,并不希望相关的数据通过不同进程间的传递,那么在同一个进程中导入本地库就显的很有效了。

一个应用程序跨过多个进程的话也容易造成很多的内存“足迹”,而且一般直接在一个进程中导入本地库的开销比另开一个进程导入本地库的开销要小。

    使用环境这块由于经验的问题,表述的不清楚。

    总之呢:当你的java应用程序必须和本地代码进行交互工作的时候,而且他们驻留在同一个进程中的时候,这个时候应该是用JNI了。

2. JNI之Hello world

   本部分我们一起来实现用JNI方式完成的helloworld功能。

  1.新建一个Helloworld.java文件,然后input如下内容:

class HelloWorld{
	private native void print(); //本地化方法,必须带上native关键字
	public static void main(String[] args){
		new HelloWorld().print();//java程序中调用print函数
	}
	static {
		System.loadLibrary("HelloWorld");//所需要调用的DLL库,该库的名字为Helloworld。
	}
}

然后执行命令:javac HelloWorld

这样会成成一个HelloWorld.class文件,然后再执行javah -jni HelloWorld 命令,会生成一个HelloWorld.h文件,内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_print
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
其中
JNIEXPORT 和 JNICALL 是java  关键字,表示该方法是本地化方法,要被java程序调用的,
然后使用VC++6.0新建一个Win32动态链接库工程,取名HelloWorld.c,然后输入:

#include <jni.h>//包含jni头文件
#include <stdio.h>
#include "HelloWorld.h"


JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *a, jobject b){
  
	printf("hello world\n");
	return ;
  }

然后实现在HelloWorld.h中的
JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *a, jobject b),记得带入参数a和b,不然会出现错误。
然后对VC++ 6.0 中进行设置:Tools->Options->Directories 添加 java 安装 目录的 include和win32目录,例如我的目录为:

C:\Java\jdk1.6.0_21\include 和 C:\Java\jdk1.6.0_21\include\win32

然后编译、链接工程,会在debug目录下生成 HelloWorld.dll 文件,将该文件拷贝到 HelloWorld.java的同一个目录下,然后在 HelloWorld.java的目录下执行 java HelloWorld 会在屏幕上输出 helloworld ,至此,我们利用JNI方式生成的helloworld完成了。

后面将会一起来学习JNI更深入的东西。



 


   

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值