JNI入门整理

来源:互联网 发布:l800清零软件中文 编辑:程序博客网 时间:2024/05/23 02:16

一.通过java代码先生成.h文件

调用带非字符类型,如整型(int),可参照下列,如为字符或字符串,阅读全文。

DOS环境下:

Java文件准备:

HelloNative.java

public class HelloNative {

public native static void greeting();

static

{

System.loadLibrary("HelloNative");

}

}

这个文件建好以后,先启动一个DOS窗口,按照下面步骤执行(注意,执行下面步骤,必须保证与Java源文件在同一目录下):

    1. 编译:javac HelloNative .java  //生成HelloNative.class
    2. 生成DLL函数所需头文件(HelloNative.h):javah -jni HelloNative

HelloNative.h内容:

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

#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     HelloNative
* Method:    greeting
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloNative_greeting
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

测试文件:

HelloNativeTest.java

class HelloNativeTest

public static void main(String[] args)

new HelloNative().greeting();

}

}

编译生成执行类文件。

创建DLL:

启动VC6.0,按以下步骤执行:

新建工程:File  --->   New    --->   Projects   --->   Win32 Dynamic-Link Library      然后输入新建工程名称,最好是保持与要建的DLL

名字一样(这是第一次做,小心为上,随便起名,与DLL不同不知道会不会有问题,改天再试),然后选择  OK  ,出现下

一个选择面板,选择  An empty dll project.  ,然后直接点   Finish   ,工程新建完毕。

环境准备:找到Java的安装目录下的 include目录(路径参照 D:\Program Files\Java\jdk1.6.0_20\include\ )将这个目录下的全部文件复制到VC6.0的安装目录下的 include目录下(路径参照 D:\Program Files\Microsoft Visual Studio\VC98\Include\ ),然后将D:\Program Files\Java\jdk1.6.0_20\include\ win32下的内容再复制到D:\Program Files\Microsoft Visual Studio\VC98\Include\下(这里出现了双份的jawt_md.h和jni_md.h拷贝,编译的事情,这里不具体研究,出问题再说),这些完成后,把Java代码准备时生成的DLL头文件 HelloNative.h 添加到上一步新建的DLL工程中,然后再新建一个DLL程序文件 HelloNative.c

HelloNative.c

#include "HelloNative.h"

#include <stdio.h>

JNIEXPORT void JNICALL Java_HelloNative_greeting(JNIEnv* env, jclass cl)

printf("Hello Native World!\n");

}

新建完成后,执行 Build  --->  Build  HelloNative.dll (或者按F7) 生成测试用的DLL文件

然后将DLL文件拷贝到测试用Java程序的执行类(*.class)所在文件下,这个练习是放到HelloNative.class和HelloNativeTest.class所在目录下,然后进入DOS窗口,执行 java HelloNativeTest(回车),就可以看到输出结果了。



如果是在MyEclipse工程中,需要进行下述操作:

将VC工程生成的DLL文件放到工程 bin目录下,这个练习是将 HelloNative.dll 放到 bin 目录下。

找到菜单  Run   --->   Open Run Dialog...   --->  Java Application(选项卡)    ,在这个选项下边,会有对应于要调用DLL工程的一个选项,点进这个选项,在详细设定面板中选择   (x)=Arguments 这个选项卡,在里有一个文本输入的项目叫 VM arguments  ,在里面输入       " -Djava.library.path=E:\JavaWork\nativeInterfaceCall\bin"      ,然后点  Run 按钮,然后就可以执行程序了。

注意,这里的" -Djava.library.path=E:\JavaWork\nativeInterfaceCall\bin",不能在程序中用System.Setproperty()设定,因为java.library.path这个属性只在JVM启动的时候读取一次,所以,程序中的任何相关设定都是不起作用的。

HelloNative.java 这种中间类不能放在包里面,就是不能指定package。

调用带字符串参数的DLL
带字符串参数的DLL调用必须借助每三方接口,确切的说,就是在要调用的DLL上再加一层接口,下述说明参照。

上述使用例程修正如下:

HelloNative.java

public class HelloNative {

//这里对应的DLL接口定义为void greeting(char *str),这么定义是因为Java和C使用的是不同的字符集标准

//C是ANSI,Java是UTF-16(这个我也是查资料,没弄的太明白,可能有误,不过基本是这么个意思)

public native static void greeting(byte[] str,int strLength);

static

{

System.loadLibrary("HelloNative");

}

}

参照无参的HelloNative.java的说明,生成HelloNative.h头文件。

HelloNativeTest.java

class HelloNativeTest

   public static void main(String[] args)
   { 
   String str = new String("Hello Native World!\n");
      new HelloNative().greeting(str.getBytes(),str.length());
   }
}

参照无参例子,新建动态链接库工程,生成DLL文件,然后将DLL放到system32下,放到别的地方也可以,不过要将你放的路径设置到系统环境变量 path 里,这样就不用运行Java的时候,总是去设定 java.library.path 这个JVM属性了。到这里,生成的是可以供windows调用的DLL。下面是参照代码:

如果是编译位于包路径下的中间件接口,使用如下格式命令

生成类文件:javac xxx.java

生成编译DLL所需头文件:javah -jni -classspath 包路径。类名(com.XXX.util.xxx)

二、另一种理解:

1.简介
  
  JNI是Java Native Interface的缩写,它的设计目的是:
  
  The standard Java class library may not support the platform-dependent features needed by your application.
  
  You may already have a library or application written in another programming language and you wish to make it accessible to Java applications
  
  You may want to implement a small portion of time-critical code in a lower-level programming language, such as assembly, and then have your Java application call these functions
  
  2.JNI的书写步骤
  
  编写带有native声明的方法的java类
  
  使用javac命令编译所编写的java类
  
  使用javah ?jni java类名生成扩展名为h的头文件
  
  使用C/C++实现本地方法
  
  将C/C++编写的文件生成动态连接库
  
  ok
  
  1) 编写java程序:
  
  这里以HelloWorld为例。
  
  代码1:
  
  class HelloWorld {
  public native void displayHelloWorld();
  
  static {
  System.loadLibrary("hello");
  }
  
  public static void main(String[] args) {
  new HelloWorld().displayHelloWorld();
  }
  }
  
  声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为native的,并且不能实现。其中方法的参数和返回值在后面讲述。
  
  Load动态库:System.loadLibrary("hello");加载动态库(我们可以这样理解:我们的方法displayHelloWorld()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary();的参数“hello”是动态库的名字。
  
  main()方法
  
  2) 编译没有什么好说的了
  
  javac HelloWorld.java
  
  3) 生成扩展名为h的头文件
  
  javah ?jni HelloWorld
  
  头文件的内容:
  /* 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:  displayHelloWorld
  * Signature: ()V
  */
  JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
  (JNIEnv *, jobject);
  
  #ifdef __cplusplus
  }
  #endif
  #endif
  
  (这里我们可以这样理解:这个h文件相当于我们在java里面的接口,这里声明了一个Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C++程序的时候所使用的方法名必须和这里的一致)。
  
  4) 编写本地方法
  
  实现和由javah命令生成的头文件里面声明的方法名相同的方法。
  
  代码2:
  
  1 #include <jni.h>
  2 #include "HelloWorld.h"
  3 #include <stdio.h>
  4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
  {
  printf("Hello world!\n");
  return;
  }
  
  注意代码2中的第1行,需要将jni.h(该文件可以在%JAVA_HOME%/include文件夹下面找到)文件引入,因为在程序中的JNIEnv、jobject等类型都是在该头文件中定义的;另外在第2行需要将HelloWorld.h头文件引入(我是这么理解的:相当于我们在编写java程序的时候,实现一个接口的话需要声明才可以,这里就是将HelloWorld.h头文件里面声明的方法加以实现。当然不一定是这样)。然后保存为HelloWorldImpl.c就ok了。
  
  5) 生成动态库
  
  这里以在Windows中为例,需要生成dll文件。在保存HelloWorldImpl.c文件夹下面,使用VC的编译器cl成。
  
  cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll
  
  注意:生成的dll文件名在选项-Fe后面配置,这里是hello,因为在HelloWorld.java文件中我们loadLibary的时候使用的名字是hello。当然这里修改之后那里也需要修改。另外需要将-I%java_home%\include -I%java_home%\include\win32参数加上,因为在第四步里面编写本地方法的时候引入了jni.h文件。
  
  6) 运行程序
  
  java HelloWorld就ok。^_^

三、绑定VC:JNI(.DLL)

 

JNI调用DLL动态库调试方法:

1. 在myeclipse(或eclipse)项目工程里指定Native libraryBuild Path)到VS生成的DLL(debug生成)目录下

2.运行myeclipsejava代码,启动进程(调用DLL

3.VS中找到tools下的 attach to process(附加进程)

再找到该 java进程,选择attach

4.如果附加成功,则会在运行java代码(调用JNI)时进入VS调试模式

参考:http://wenku.baidu.com/view/f688068ccc22bcd126ff0c60.html

 

 

原创粉丝点击