Part1. JNI(Java Native Interface)介绍和HelloWorld程序编写

原文地址http://electrofriends.com/articles/jni/jni-part1-java-native-interface/

JNI简介,JNI的意义以及特点

  • JNI指定了Java代码和本地代码之间的通信协议。
  • JNI使得Java代码可以和使用不同语言(如C/C++等)编写的本地代码进行交互。
  • 本地代码通常可以直接访问CPU和寄存器,所以它们比解释代码(如JAVA)执行得更快。
  • Java代码中的一些方法有时需要在Java中声明使用,但却要通过别的代码来实现。

JNI可以让程序员做这些事情

  • 通过控制硬件,使用一些平台特性,不再局限在JVM当中。
  • 使用本地已经提供的代码库而不用重复发明轮子。

JNI的缺点

  • 不再是平台无关。
  • 代码健壮性存在一定问题。当Java代码通过JNI调用的本地代码存在内存泄漏或者是空指针等问题时,在Java代码中很难进行调试。

JNI在系统中的位置

  • JNI作为JVM实现的一部分,JNI是一个本地代码和Java代码之间的双向接口。它使得不同的代码可以互相调用。
  • 作为一个双向接口,JNI支持两种类型的本地代码:native libraries 和 native applications。
    Role of JNI

HelloWorld

下面通过实例介绍如何通过JNI让Java代码去调用一个简单的C程序。
主要包括以下几个步骤:

  1. 编写Java类,在类中声明一个本地方法,并在main()方法中调用它。
  2. 编译.java文件,生成.class文件。
  3. 使用javah工具生成C代码的.h头文件,并在.c文件中实现.h头文件声明的方法。
  4. 把C程序编译成.dll动态链接库文件。
  5. 调用HelloWorld.class

步骤一 编写Java类:

/**
* HelloWorld.java
**/
class HelloWorld {
    public native void print();  //native method
    static   //static initializer code
    {
        System.loadLibrary("CLibHelloWorld");
    } 

    public static void main(String[] args)
    {
        HelloWorld hw = new HelloWorld();
        hw.print();
    }
}

在这里要注意两个地方:
1.首先是使用native关键字声明了一个本地方法。

public native void print();

这是在告诉编译器print()方法是一个本地方法,它的实现应该在外部库中去找。

2.然后是在static块中加载了动态链接库

static   //static initializer code
    {
        System.loadLibrary("CLibHelloWorld");
    } 

被static围起来的代码块将在调用print()方法之前被执行,也就是系统将会把包含了print()方法的具体实现的动态链接库事先加载进来。

步骤二 编译.java文件

javac HelloWorld.java

得到HelloWorld.class类

步骤三 使用javah工具生成C代码的.h头文件

javah –jni HelloWorld

生成的头文件为HelloWorld.h,它是这样子的:

/**
* HelloWorld.h
**/

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* 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 void JNICALL Java_HelloWorld_print
  (JNIEnv *, jobject);

这里声明了一个返回值为void,名为Java_HelloWorld_print的C函数。
第一个参数是JNI运行环境的指针。
第二个存数是HelloWorld对象的引用。

然后我们来编写一个本地的C程序,如下:

#include "HelloWorld.h"
#include "jni.h"
#include  "stdio.h"

JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
  printf("Hello world\n");
  return;
}

代码实现了.h头文件中声明的函数。很简单地打印出”Hello world\n”。

步骤四 把C程序编译成.dll动态链接库文件
Part2. 使用Visual Studio把C代码编译成.dll文件

步骤五 调用HelloWorld.class
如果一切顺利,将会看到控制台打印出Hello world。
当Java代码无法找到.dll或者方法名不对时,会报错java.lang.UnsatisfiedLinkError。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值