`

JAVA中native方法调用

阅读更多
使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。这些函数的实现体在DLL中,JDK的源代码中并不包含,你应该是看不到的。对于不同的平台它们也是不同的。这也是java的底层机制,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。native的意思就是通知操作系统,这个函数你必须给我实现,因为我要使用。所以native关键字的函数都是操作系统实现的,java只能调用。 

参考网站:【http://www.androidnote.com/index.asp】

在java中native是关键字。它一般在本地声明,异地用C和C++来实现。它的声明有几点要注意:1)native与访问控制符前后的关系不受限制。2)必须在返回类型之前。3)它一般为非抽象类方法。4)native方法在异地实现,象抽象方法一样,所以没有方法体,以分号结束。如下列5种声明:

         native public void f();                         正确。

         private native void f();                        正确。

         protected int native f();                      错误,返回类型位置不对,返回类型必须在native之后。

         public abstract native void f();            native必然不是abstract的。

         native int f(){}                                     错误,因为存在方法体{}

         public static native f();                         正确。static与native方法位置随意。

       下例是比较典型的native的使用方式,用loadLibrary导入存在源文件目录下的*.dll文件,然后定义native方法时,与c/c++实现的函数有相同的参数和返回类型。

public class OpticalFlowCalculateDll{

    static{

        System.loadLibrary("OpticalFlow");

    }

   

    public native static void setImage();   

    public native static int[] getGoodFeatureListForTrack();   

    public native static int[] getMatchedFeatureList();   

    public native static int getFeatureListSize();   

    public native static void dispose();

}  

      再展开来说JNI,JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。JNI是JDK的一部分,用于为Java提供一个本地代码的接口。通过使用JNI编写的程序能够确保你的代码能够完全的移植到所有的平台。JNI使得运行在JVM虚拟机上的Java代码能够操作使用其它语言编写的应用程序和库,比如 C/C++以及汇编语言等。此外JNI提供的某些API还允许你把JVM嵌入到本地应用程序中。

  

  使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。

JNI的设计目的:

  ·标准的java类库可能不支持你的程序所需的特性。

  ·或许你已经有了一个用其他语言写成的库或程序,而你希望在java程序中使用它。

  ·你可能需要用底层语言实现一个小型的时间敏感代码,比如汇编,然后在你的java程序中调用这些功能。

       本文将通过一个实例来阐述使用VC++6.0来实现JNI的完整过程。使用JNI来整合本地代码和Java代码的步骤是确定的,没有再创作的余地,所以读者可以通过本文的步骤来逐步认识到,其实Java也是"没有什么不可以"的。

一、JNI的实现任务描述:在Java中调用windows下的消息框函数,并且从Java中传递一个字符串作为MessageBox函数的显示文本参数,显示在消息框的中间。下面让我们一起进入这一奇妙的旅程。

Step 1:写一个Java类,在这个类中包含了需要调用的本地方法的描述。

//WinMsgBox.java

package edu.netcom.jni;

public class WinMsgBox

{

static{

System.loadLibrary("WinMsgDll");    // (1)

}

public native void showMsgBox(String str); // (2)

}


(1)中WinMsgDll是动态链接文件的文件名,不用加扩展名,因为在不同的平台下动态链接文件扩展名是不同的,由JVM自动识别,比如在 Solaris下,会被转换为WinMsgDll.so;而Win32环境下会转换为WinMsgDll.dll。这个文件名必须和Step 4中生成的文件名一致。这个文件的存放位置也很重要,它只能被放在JVM属性值java.library.path中指定的文件夹中。这个属性值可以使用 System.getProperty("java.library.path");来查看。一般情况下,至少放在这几个位置是确定可靠的,windows安装目录下的system32下面,JDK安装目录下的bin下面,以及调用主类文件的当前目录。

(2)中指明了你必须用本地代码实现的方法。

Step 2:提示符下使用命令javac -d . WinMsgBox.java编译Step 1编写的java文件。

此时会在当前目录下建立一个edu\netcom\jni目录结构,并且一个WinMsgBox.class文件存在其中。

Step 3:提示符下使用命令javah -jni edu.netcom.jni.WinMsgBox,此时会在当前目录下产生一个edu_netcom_jni_WinMsgBox.h文件,注意这个文件名是由(包名+类名)组成,中间用(_)隔开。此文件内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>                       // (1)

/* Header for class edu_netcom_jni_WinMsgBox */

#ifndef _Included_edu_netcom_jni_WinMsgBox

#define _Included_edu_netcom_jni_WinMsgBox

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class:     edu_netcom_jni_WinMsgBox

* Method:    showMsgBox

* Signature: (Ljava/lang/String;)V       // (2)

*/

JNIEXPORT void JNICALL Java_edu_netcom_jni_WinMsgBox_showMsgBox

(JNIEnv *, jobject, jstring);           // (3)

#ifdef __cplusplus

}

#endif

#endif

(1)包含的jni.h存在于JDK安装目录下的include下面。

(2)(Ljava/lang/String;)V这是函数的标记符,当从本地方法端访问Java端的方法时,会用到这个标记符。JNI中为每种数据类型也定义了标记符,标记符的规则请查看JNI标准文档。

(3)在WinMsgBox.java中本地方法void showMsgBox(String str);的定义,被映射为JNIEXPORT void JNICALL Java_edu_netcom_jni_WinMsgBox_showMsgBox(JNIEnv *, jobject, jstring); 其中函数名的映射规则是(Java_包名_类名_方法名),如果存在重载的方法,则在后面还会增加每个参数的标记符。每一个方法映射到本地C函数后都会增加两个参数:JNIEnv *和jobject,关于这两个参数的用法将在后面阐述。另外,所有Java中的数据类型都会按一定规则进行映射为本地数据类型,这些数据类型都是在 jni.h中定义的。下面分别按照基本数据类型,和对象类型列出。

Step 4:使用VC来编写本地方法的实现函数,最后编译成.dll文件。过程如下:

1) 选择new->projects(选择Win32 Dynamic-Link Library,以Step 1中指定的库名WinMsgDll作为工程名)->OK->An ampty DLL project->Finish。

2) 选择Tools->Options->Directories(添加目录D:\J2SDK1.4.2_03\INCLUDE和D: \J2SDK1.4.2_03\INCLUDE\WIN32)。在这些目录中包含JNI所需的头文件。

3) 将Step 3生成的edu_netcom_jni_WinMsgBox.h拷贝到WinMsgDll工程文件夹中。然后FileView中添加这个头文件。

4) 添加源文件WinMsgDll.cpp,内容如下:

#include "windows.h"

#include "edu_netcom_jni_WinMsgBox.h"

/*

* Class:     edu_netcom_jni_WinMsgBox

* Method:    showMsgBox

* Signature: (Ljava/lang/String;)V

*/

JNIEXPORT void JNICALL Java_edu_netcom_jni_WinMsgBox_showMsgBox

(JNIEnv * env, jobject obj, jstring str){

const char *msg;

msg = env->GetStringUTFChars(str,0);

MessageBox(NULL,msg,"Java invoke",MB_OK);

env->ReleaseStringUTFChars(str,msg);

}

5) 编译生成WinMsgBox.dll文件。并将这个.dll文件拷贝到Step 1中说明的目录中。

注意:

1) 我们知道dll文件有两种指明导出函数的方法,一种是在.def文件中定义,另一种是在定义函数时使用关键字 __declspec(dllexport)。而在JNI中函数定义中的关键字JNIEXPORT实际在jni_md.h中如下定义,#define JNIEXPORT __declspec(dllexport),可见JNI默认的导出函数使用第二种。使用第二种方式产生的导出函数名会根据编译器发生变化,在有的情况下会发生找不到导出函数的问题(我们在JSP中使用JNI时就发生了这种问题,百思不得其解,后来强行加入一个.def文件就解决了)。因此最好是使用第一种方法自己定义一个.def文件来指明导出函数,这种情况下会强制使用第一种方式产生导出函数。本例中可以加入一个WinMsgDll.def文件,内容如下:

LIBRARY      "WinMsgDll"

DESCRIPTION 'message Windows Dynamic Link Library'

EXPORTS

    ; Explicit exports can go here

Java_edu_netcom_jni_WinMsgBox_showMsgBox

2) 从本例中,我们可以看到WinMsgBox.java决定了edu_netcom_jni_WinMsgBox.h,而后者又决定了 WinMsgDll.dll,也就是说,这是一个"牵一发而动全身"的过程,如果你改动了WinMsgBox.java,就一定要把整个步骤都走一遍(这一点一定要切记,因为这也是我们跌得鼻青脸肿后才得出的警世良言)。

3) 生成的.dll文件一定要正确拷贝到Step 1说明的目录中,本例中是将生成的WinMsgDll.dll和Step 5中的测试文件放在同一个目录下的(这也是我们困惑了很久才解决的问题)。

Step 5:编写一个测试文件来测试对WinMsgDll.dll的调用。测试文件TestJNI.java内容如下:

//TestJNI.java

import edu.netcom.jni.WinMsgBox;

public class TestJNI

{

public static void main(String[] args){

     WinMsgBox box = new WinMsgBox();

     box.showMsgBox("Wonderful!!");

   }

}

编译,运行,windows下的对话框跃然屏幕中间。到此为此,整个JNI的实现过程就已经完成了。

http://hi.baidu.com/gabe2008/blog/item/bb07d6879c67ea3566096e28.html
分享到:
评论

相关推荐

    Java中native方法学习

    Java中native方法学习 系统调用

    使用Java Native Interface调用本地C++代码.txt

    在这个例子中,我们使用Java Native Interface(JNI)来调用本地的C++代码。首先,我们需要在Java类中声明一个native方法,并使用`native`关键字来修饰它。然后,我们需要使用`System.loadLibrary()`方法来加载本地...

    Android JNI native调用 java层demo TESTJNI.zip

    android jni native C++访问java层数组,java类对象属性和方法,回调接口和线程回调接口 内附可以正常使用的demo

    native server调用javaserver

    native server调用javaserver

    JS和Android的Native方法互调用所有情况测试

    JS和Android的Native方法互调用所有情况测试 亲测!可用! 用于Android和HTML5混合开发中壳子的使用 后续将加入: Java类结构 和 Js库基本命名规则和构建 集成基本的友盟组件测试 全功能灵活集成的...

    JAVA调用C++的dell应用例子

    Jni(Java Native Interface)是sun提供的java与系统中的原生方法交互的技术(在windows\linux系统中,实现java与native method互调)。目前只能由c/c++实现。后两个都是sourceforge上的开源项目,同时也都是基于jni...

    JNI与Java方法的相互调用

    JNI与Java方法的相互调用学习笔记代码。可以新建一个项目,把其中的c++代码拷贝到native-lib.cpp文件中,修改jni中的方法名即可

    Java 调用 TSC标签打印机

    1、该练习是 JNA(Java Native Access)调用 TSC 打印机的 dll 文件,操作 TSC 打印机的练习。 2、包结构 │ ReadMe.txt │ ├─DLL │ 32bit.zip │ 64bit.zip │ ├─lib │ jna.jar │ ├─ReadMe │ ...

    java使用JNA(Java Native Access)调用dll的方法

    java使用JNA(Java Native Access)调用windows系统的dll文件的例子

    Java中Native关键字的作用

    初次遇见 native是在 java.lang.Object 源码中的一个hashCode方法:  public native int hashCode();  为什么有个native呢?这是我所要学习的地方。所以下面想要总结下native。  一、认识 native 即 JNI,Java...

    Android 和 IOS WebView javaScript与 Native 互相调用(JS 与O-C Java )

    Android 和 IOS WebView javaScript与 Native 互相调用(JS 与O-C Java )

    实用技术在Android 应用中调用 C++ 代码并在新线程中执行 Java 静态方法

    这是 Kotlin 语言编写...这个接口函数的作用是创建新线程,并在新线程中调用 callJavaStaticMethod 方法,这个方法会获取当前线程的 JNIEnv 对象和 Java 类对象,并通过这些对象调用 Java 层的静态方法 staticMethod。

    java调用dll最简单的方法

    在Java中调用DLL(Dynamic Link Library)文件,可以使用Java的本地方法接口(JNI,Java Native Interface)来实现。JNI允许Java程序与本地代码进行交互,从而实现跨平台的功能。

    JNI--java调用不同平台的动态链接库,dll,so,完美,全教程

    我们知道,使用 JNI 调用 .dll/.so 共享类库是非常非常麻烦和痛苦...使用 JNA ,不需要再编写适配用的 .dll/.so ,只需要在 Java 中编写一个接口和一些代码,作为 .dll/.so 的代理,就可以在 Java 程序中调用 dll/so 。

    Java语言如何调用C++语言编写的本地方法

    该文档详细介绍了在Java代码中如何调用C或C++代码。主要思想是:将C或C++代码大包成动态链接库,然后共Java代码在执行时调用。

    Java Native Interface简介

    JNI是Java Native Interface的缩写,Java Native Interface(JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用...

    java的JNI本地调用

    JNI(java native interface)java本地接口,主要为了是实现java对本地函数的调用, 通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。

    NativeActivity通过jni调用java层的Android API

    1. 继承Nativity,打通native和java层 public class MyNativeActivity extends NativeActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.v...

    JS调用Android Native API

    JS调用Android Native API,在webview中通过js代码调用本地的java代码,比如:可以通过网页中的js代码调用android的音频服务播放音乐等等

    java调用微信支付demo

    java 调用微信支付demo 微信支付java 调用微信支付demo 微信支付java 调用微信支付demo 微信支付java 调用微信支付demo 微信支付

Global site tag (gtag.js) - Google Analytics