zoukankan      html  css  js  c++  java
  • 【转载】Windows环境下JNI的实现实例

    转自:http://blog.csdn.net/jjunjoe/article/details/6987183

     一、关于JNI:
    JNI(Java Native Interface):Java本地调用。JNI是 Java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定被支持就可以了。

    JNI也有它的缺陷:
    1、潜在的安全隐患。
    因为本机方法实行市级的机器代码,它有权使用主机的任何资源。也就是说,本机代码不受Java执行环境的限制。
    2、丧失了可一致性。
    因为本机代码是包含在动态库中的(Windows环境是DLL,其他环境如Linux也是对应的动态库.so)。它必须存在于执行Java程序的机器上。而且因为每一个本机方法都依赖于CPU和操作系统。这样一个运用本机方法的Java程序只能在一个已经安装了可兼容动态库的机器上运行。

    二、JNI在Windows环境的实现:
    1、在Java程序代码中对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。
    这里我用eclipse建了一个Java项目,名为JniClient,里面就一个Java文件,在包com.test下,名为JniClient.java,内容如下:
    package com.test;

    public class JniClient {
        public static void main(String[] args) {

            new JniClient().test("Hello, world!");
        }

        static {
            System.loadLibrary("JniServer");
        }

        public native void test(String instring);
    }

    2、编译JniClient工程。
    1)在cmd命令行中,运行:javac JniClient
    生成class文件JniClient.class
    如果是用eclipse建工程,并且选上了自动编译选项,在bin/com/test目录下就已经有JniClient.class了,这步就不需要了。
    2)在cmd命令行中,定位路径到工程的bin目录(如果不定位到这里就会出现无法访问错误,具体原因我就没有去查找了),运行:javah com.test.JniClient
    这里因为我的JniClient.java是在com.test包中,要根据自己具体定义的包输入命令。
    在bin目录下会生成.h头文件,在后面的动态库中需要用到这个头文件。我的示例生成的是:com_test_JniClient.h。
    其代码内容如下:
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_test_JniClient */

    #ifndef _Included_com_test_JniClient
    #define _Included_com_test_JniClient
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_test_JniClient
     * Method:    test
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_com_test_JniClient_test
      (JNIEnv *env, jobject arg, jstring instring);

    #ifdef __cplusplus
    }
    #endif
    #endif
    注意:函数名称和自动生成的.h文件中规定的一致,命名规则是: Java_使用类_方法名,所以上面的方法名是:Java_com_test_JniClient_test。
    然后注释说不要编辑这个头文件,其实编辑也没关系的,比如我看默认生成的函数名没带参数,就加上了,也不会有问题。原本是:
    JNIEXPORT void JNICALL Java_com_test_JniClient_test
      (JNIEnv *, jobject, jstring);

    3、创建动态库(我用的VC++6.0)。
    1)新建一个空的动态库。
    2)将Java SDK安装目录下的jni.h,jni_md.h文件拷贝到工程目录下(我的jni.h文件在C:Program FilesJavajdk1.6.0_14include下面,jni_md.h文件在C:Program FilesJavajdk1.6.0_14includewin32下面,根据自己的安装目录去找。最好拷贝到VC的安装目录的Include目录下,比如我机器上的目录是:C:Program FilesMicrosoft Visual StudioVC98Include,这样以后所有的JNI要用到的这两个头文件都不用在工程中添加了)。
    3)将com_test_JniClient.h头文件拷贝到工程目录下面。
    4)完成com_test_JniClient.h对应的.cpp实现文件,比如com_test_JniClient.cpp,然后实现com_test_JniClient.h的函数。
    #include "com_test_JniClient.h"
    #include "myfunc.h"

    JNIEXPORT void JNICALL Java_com_test_JniClient_test
      (JNIEnv *env, jobject arg, jstring instring)
    {

        const char *str = (const char *)env->GetStringUTFChars(instring, JNI_FALSE);
        printf("%s ",str);
        testfunc(str);
        env->ReleaseStringUTFChars(instring,str);
        return;
    }
    在实现函数中,我还调用了另外一个C函数testfunc。
    其头文件为myfunc.h,内容如下:
    #ifdef __cplusplus
    extern "C" {
    #endif

    void testfunc(const char *str);

    #ifdef __cplusplus
    }
    #endif

    其实现文件为myfunc.cpp,内容如下:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "myfunc.h"

    void testfunc(const char *str)
    {
        printf("str = %s ",str);

        return;
    }

    5)编译生成动态库JniServer.dll。

    4、将动态库JniServer.dll拷贝到JniClient工程文件目录下面。
    5、运行JniClient.class,控制台输出如下信息:
    Hello, world!
    str = Hello, world!

    OK,Windows上Jni的实现到此完成,实际开发中要注意数据类型,考虑Java和VC的接口问题,用jint  jstring等。

  • 相关阅读:
    5.22 css和基本选择器
    5.21http网页基础
    ArrayList类源码浅析(二)
    ArrayList类源码浅析(一)
    Long类源码浅析
    Integer类源码浅析
    JDK中String类的源码分析(二)
    JDK中String类的源码分析(一)
    Struts2漏洞修复总结
    [LeetCode]-011-Longest Common Prefix
  • 原文地址:https://www.cnblogs.com/YangtzeYu/p/6226326.html
Copyright © 2011-2022 走看看