JAVA JNI 原理+实践

概述

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

有了JAVA标准平台的支持,使JNI模式更加易于实现和使用。在此总结了下面这个知识图:


实践

编写JNI接口类

public class HelloWorld {
    
    static 
    {
        /// 需要加载的动态库名称
        System.loadLibrary("HelloWorld");
    }
    
    /// 使用关键字 “native” 定义接口方法
    public native String GetHello();
    
    public void DisplayHello()
    {
        String str_tmp = GetHello();
        System.out.println("Class[HelloWorld]:" + str_tmp);
    }

}


生成JNI接口文件

1、进入src目录下,编译JAVA类,
命令:

javac ./JinInterface/HelloWorld.java
在该HelloWorld.java所在目录下生成HelloWorld.class

2、使用javah生成头文件,
命令:
javah -jni JinInterface.HelloWorld
在当前目录下生成JinInterface_HelloWorld.h头文件,此文件供C、C++程序来引用并实现其中的函数

JinInterface_HelloWorld.h 文件内容如下:

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

#ifndef _Included_JinInterface_HelloWorld
#define _Included_JinInterface_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JinInterface_HelloWorld
 * Method:    GetHello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_JinInterface_HelloWorld_GetHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

编译动态库

1、引用JNI头文件(JinInterface_HelloWorld.h),实现JNI头文件中的接口方法,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "JinInterface_HelloWorld.h"

JNIEXPORT jstring JNICALL Java_JinInterface_HelloWorld_GetHello
  (JNIEnv *env, jobject)
{
	char p_str[] = "Java_JinInterface_HelloWorld_GetHello : HelloWorld";

	// 定义java String类 strClass  
    jclass strClass = (env)->FindClass("Ljava/lang/String;");  

    // 获取java String类方法String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String  
    jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); 

    // 建立byte数组  
    jbyteArray bytes = (env)->NewByteArray((jsize)strlen(p_str));  

    // 将char* 转换为byte数组  
    (env)->SetByteArrayRegion(bytes, 0, (jsize)strlen(p_str), (jbyte*)p_str); 

    //设置String, 保存语言类型,用于byte数组转换至String时的参数  
    jstring encoding = (env)->NewStringUTF("GB2312");   

    //将byte数组转换为java String,并输出  
    return (jstring)(env)->NewObject(strClass, ctorID, bytes, encoding);
}

编译成功后,生成动态库。


JAVA 通过JNI调用动态库

import JinInterface.HelloWorld;

public class HelloWorldTest {

    static HelloWorld m_hello_world = new HelloWorld();
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        m_hello_world.DisplayHello();

    }

}

运行结果:Class[HelloWorld]:Java_JinInterface_HelloWorld_GetHello : HelloWorld


-------------------------------------------------------------------------------------------------------------------------------

注意事项:

1、动态库存放路径;目前使用的方法是,直接将动态库所在路径配置到环境变量PATH里面。

2、调用动态库时,需要注意JDK版本,如果编译出来的动态库是32位的,使用64位JDK无法正常调用。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值