eclipse中JNI实战

1.何为JNI?

JNI是JAVA标准平台中的一个重要功能,它弥补了JAVA的与平台无关这一重大优点的不足,在JAVA实现跨平台的同时,也能与其它语言(如C、C++)的动态库进行交互,给其它语言发挥优势的机会。有了JAVA标准平台的支持,使JNI模式更加易于实现和使用

这里不再赘述,附上别人总结的图:

技术分享

原图链接:http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.html

知识补充:

存根类(stub),它实现了一个接口,但是实现后的每个方法都是空的。

它的作用是:如果一个接口有很多方法,如果要实现这个接口,就要实现所有的方法。但是一个类从业务来说,可能只需要其中一两个方法。如果直接去实现这个接口,除了实现所需的方法,还要实现其他所有的无关方法。而如果通过继承存根类就实现接口,就免去了这种麻烦。


头文件

百度解释:一般会把用来#include的文件的扩展名叫.h,称其为头文件。 #include文件的目的就是把多个编译单元(也就是c或者cpp文件)公用的内容,单独放在一个文件里减少整体代码尺寸;或者提供跨工程公共代码。


2 javah

使用Javah 可以获取您的 Java 源文件并生成 C/C++头文件,其中包含您的 Java 代码中所有本地方法(native方法)的 JNI 存根(stub,C头文件)。


3.eclipse配置javah


      JNI的编写步骤

a、编写带有native声明的方法的java类

b、使用javac命令编译a中实现的类

c、javah -jni java类名生成扩展名为h的头文件

d、使用C/C++实现本地方法

e、将d中的本地方法生成动态链接库



首先新建一个包含本地方法(native方法)的类,native标识符暗示这些方法是有实现体的,只不过这些实现体是非java的,代码如下:

/**
 * 
 */
 package com.magc.jni;

 /**
 * @author magc
 *
 */
 public class HelloWorld {
    
    static {
        
        System.loadLibrary("Hello");
        
    }

    public     native void DisplayHello();
    /**
     * @param args
     */
    public static void main(String[] args) {

        new HelloWorld().DisplayHello();
    }

}

注:

loadloadLibrary区别

  1. 它们都可以用来装载库文件,不论是JNI库文件还是非JNI库文件。在任何本地方法被调用之前必须先用这个两个方法之一把相应的JNI库文件装载。

    2.System.load 参数为库文件的绝对路径,可以是任意路径。
    例如你可以这样载入一个windows平台下JNI库文件:
    System.load("C:\\Documents and Settings\\TestJNI.dll");

    3. System.loadLibrary 参数为库文件名,不包含库文件的扩展名。
    例如你可以这样载入一个windows平台下JNI库文件
    System. loadLibrary ("TestJNI");

    这里,TestJNI.dll 必须是在java.library.path这一jvm变量所指向的路径中。
    可以通过如下方法来获得该变量的值:
    System.getProperty("java.library.path");
    默认情况下,在Windows平台下,该值包含如下位置:
    1)和jre相关的一些目录
    2)程序当前目录
    3)Windows目录
    4)系统目录(system32)
    5)系统环境变量path指定目录。

classpath与java.library.path区别

classpath路径下,只能是jar或者class 文件,否者会报错,因为他们会被load到JVM


要想java程序找到共享库还是要在执行java程序的时候指定java.library.path,用eclipse的话可以设置如下:

  1. Properties->Run/Debug settings->Arguments->VM arguments  

  2. -----------------------------------------  

  3. -Djava.library.path=/home/miaoyachun/workspace/JNIC/Release  



需要使用外部工具,在我们运行java程序按钮的旁边,或者通过菜单栏上的run选项进入External tool中并选择 External tool configuration,新建一个启动项HelloWorld

参数如下:

Location:

D:\program files\Java\jdk1.7.0_51\bin\javah.exe

Working Directory

${project_loc}

Arguments:

-v -classpath "${project_loc}/bin" -d "${project_loc}/jni" ${java_type_name}  (这里v表示启用详细输出)

技术分享



4.生成实现函数头文件(扩展名为h)

运行该工具,光标必须定位在在需要生成头文件的java源文件中,否则会报${project_loc}这个变量为空错误

技术分享



在当前项目的jni目录下生成了com_magc_jni_HelloWorld.h头文件,此文件供C、C++程序来引用并实现其中的函数

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
<jni.h>
/* Header for class com_magc_jni_HelloWorld */
#ifndef _Included_com_magc_jni_HelloWorld
#define 
_Included_com_magc_jni_HelloWorld
#ifdef __cplusplus
extern "C" 
{
#endif
/*
 * Class:     com_magc_jni_HelloWorld
 * Method:    
DisplayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL 
Java_com_magc_jni_HelloWorld_DisplayHello
  (JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

注:1)、此头文件是不需要用户编译的,直接供其它C、C++程序引用。

2)、此头文件中的Java_com_magc_jni_HelloWorld_DisplayHello(JNIEnv *, jobject)方法,是将来与动态链接库交互的接口,并需要名字保持一致。



5.使用C/C++实现本地方法生成动态链接库(windows下扩展名为DDL,linux下扩展名为so):


#include <jni.h>
#include "com_magc_jni_HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_com_magc_jni_HelloWorld_DisplayHello
(JNIEnv *env, jobject obj)
{
    printf("From jni_helloworldImpl.cpp :");
    printf("Hello world ! \n");
    return;
}

此C++文件实现了上述头文件中的函数,注意方法函数名要保持一致。


编译生成动态链接库文件,有了具体实现的动态库,拷贝到项目的bin目录下,就可以运行JAVA调用JNI程序类的native方法了


本文出自 “梦想属于勇敢者-天行者” 博客,请务必保留此出处http://tianxingzhe.blog.51cto.com/3390077/1652034

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。