JNI

JNI
       ☆ JNI
   【摘】Java 本机接口(Java Native Interface (JNI))是一个本机编程接口,它是 Java 软件开发工具箱(Java Software Development Kit (SDK))的一部分。JNI 允许 Java 代码使用以其它语言(譬如 C 和 C ++ )编写的代码和代码库。Invocation API(JNI 的一部分)可以用来将 Java 虚拟机(JVM)嵌入到本机应用程序中,从而允许程序员从本机代码内部调用 Java 代码。


       ☆ JNI [Java调用其他语言]运用方向【摘】
   1 )希望用更低级、更快的编程语言去实现对时间有严格要求的代码。

   
2 )希望从 Java 程序访问旧代码或代码库。

   
3 )需要标准 Java 类库中不支持的依赖于平台的特性。


       ☆ 步骤【摘】
   1 )编写 Java 代码。从编写 Java 类开始,这些类执行三个任务:声明将要调用的本机方法;装入包含本机代码的共享库;然后调用该本机方法。

  
2 )编译 Java 代码。在使用 Java 类之前,必须成功地将它们编译成字节码。

  
3 )创建 C / C ++  头文件。C / C ++  头文件将声明想要调用的本机函数说明。然后,这个头文件与 C / C ++  函数实现(请参阅步骤  4 )一起来创建共享库(请参阅步骤  5 )。

  
4 )编写 C / C ++  代码。这一步实现 C 或 C ++  源代码文件中的函数。C / C ++  源文件必须包含步骤  3  中创建的头文件。

  
5 )创建共享库文件。从步骤  4  中创建的 C 源代码文件来创建共享库文件。

  
6 )运行 Java 程序。运行该代码,并查看它是否有用。我们还将讨论一些用于解决常见错误的技巧。


       ☆ 第一步:编写Java代码 

package jnidemo;

public class JavaCallC {
    
/**
     * native 关键字告诉 Java 编译器:方法是用 Java 类之外的本机代码实现
     * 只能在 Java 类中声明本机方法,而不能实现它
     
*/
    
public native void voidMethod();
    
public native int intMethod(int arg);
    
public native boolean boolMethod(boolean arg);
    
public native int intArrayMethod(int [] args);
    
public native String [] strArrayMethod(String [] args);
    
public native String [] getName();

    
public static void main(String[] args) {
        
/**
         * 装入了包含本机方法的实现的共享库文件
         * (基于 UNIX 的平台上的共享库文件通常含有前缀"lib")
         
*/
        System.loadLibrary(
"libJavaCallC");
        
        JavaCallC javaCallC
=new JavaCallC();
        javaCallC.voidMethod();
        System.out.println(
"intMethod="+javaCallC.intMethod(2008));
        System.out.println(
"boolMethod="+javaCallC.boolMethod(true));
        System.out.println(
"intArrayMethod="+javaCallC.intArrayMethod(new int[]{1,2,3}));
        String [] result
=javaCallC.strArrayMethod(new String []{"happy","new","year"});
        
for(String str:result){
            System.out.print(str);
        }
        result
=javaCallC.getName();
        
for(String str:result){
            System.out.print(str);
        }
    }
}


       ☆ 第二步:编译Java代码
javac JavaCallC.java


       ☆ 第三步:创建C头文件
javah jnidemo.JavaCallC
得到头文件如下:

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

#ifndef _Included_jnidemo_JavaCallC
#define _Included_jnidemo_JavaCallC
#ifdef __cplusplus
extern 
"C" {
#endif
/*
 * Class:     jnidemo_JavaCallC
 * Method:    voidMethod
 * Signature: ()V
 
*/
JNIEXPORT 
void JNICALL Java_jnidemo_JavaCallC_voidMethod
  (JNIEnv 
*, jobject);

/*
 * Class:     jnidemo_JavaCallC
 * Method:    intMethod
 * Signature: (I)I
 
*/
JNIEXPORT jint JNICALL Java_jnidemo_JavaCallC_intMethod
  (JNIEnv 
*, jobject, jint);

/*
 * Class:     jnidemo_JavaCallC
 * Method:    boolMethod
 * Signature: (Z)Z
 
*/
JNIEXPORT jboolean JNICALL Java_jnidemo_JavaCallC_boolMethod
  (JNIEnv 
*, jobject, jboolean);

/*
 * Class:     jnidemo_JavaCallC
 * Method:    intArrayMethod
 * Signature: ([I)I
 
*/
JNIEXPORT jint JNICALL Java_jnidemo_JavaCallC_intArrayMethod
  (JNIEnv 
*, jobject, jintArray);

/*
 * Class:     jnidemo_JavaCallC
 * Method:    strArrayMethod
 * Signature: ([Ljava/lang/String;)[Ljava/lang/String;
 
*/
JNIEXPORT jobjectArray JNICALL Java_jnidemo_JavaCallC_strArrayMethod
  (JNIEnv 
*, jobject, jobjectArray);

/*
 * Class:     jnidemo_JavaCallC
 * Method:    getName
 * Signature: ()[Ljava/lang/String;
 
*/
JNIEXPORT jobjectArray JNICALL Java_jnidemo_JavaCallC_getName
  (JNIEnv 
*, jobject);

#ifdef __cplusplus
}
#endif
#endif
  除了 Java 声明中的一般参数以外,所有这些函数的参数表中都有一个指向 JNIEnv 和 jobject 的指针。指向 JNIEnv 的指针实际上是一个指向函数指针表的指针,这些函数提供各种用来在 C 和 C ++  中操作 Java 数据的能力。

  jobject 参数引用当前对象。因此,如果 C 或 C
++  代码需要引用 Java 函数,则这个 jobject 充当引用或指针,返回调用的 Java 对象。


       ☆ 第四,五步:编写C代码[Windows下得到DLL]
   1 )开启VC;

  
2 )新建 -> Win32 Dynamic - Link Library工程,工程名为libJavaCallC;

  
3 )在Source Files下新建C文件javaCallC.c;

  
4 )在HeaderFiles下引入头文件jnidemo_JavaCallC.h;

  
5 )配置路径,在Tools -> Options -> Directories下加入JAVA的头文件,例如:
   C:/Program Files/Java/jdk1.
6.0 /include
   C:/Program Files/Java/jdk1.
6.0 /include/win32
不然编译会报错[Cannot open include file: 
' jni.h ' ]
javaCallC.c
  API和类型对照请参考后面的参考资料。
  附:C 和 C++  函数实现的比较
  C 和 C
++  代码几乎相同;唯一的差异在于用来访问 JNI 函数的方法。在 C 中,JNI 函数调用由“( * env) -> ”作前缀,目的是为了取出函数指针所引用的值。在 C ++  中,JNIEnv 类拥有处理函数指针查找的内联成员函数。下面将说明这个细微的差异,其中,这两行代码访问同一函数,但每种语言都有各自的语法。
    C 语法: jsize len 
=  ( * env) -> GetArrayLength(env,array); 
    C
++  语法: jsize len  = env -> GetArrayLength(array); 
Linux得到SO


       ☆ 第六步:运行JAVA程序
   1 )将libJavaCallC.dll放在环境变量的路径中;

  
2 )运行:java jnidemo.JavaCallC
运行结果


       ☆ JNI[其他语言调用JAVA]
   1 )希望实现的这部分代码是平台无关的,它将用于跨多种平台使用的功能。

  
2 )需要在本机应用程序中访问用 Java 语言编写的代码或代码库。

  
3 )希望从本机代码利用标准 Java 类库


       ☆ 开发步骤【摘】
   1 )编写 Java 代码。这个步骤包含编写一个或多个 Java 类,这些类实现(或调用其它方法实现)您想要访问的功能。

  
2 )编译 Java 代码。在能够使用这些 Java 类之前,必须成功地将它们编译成字节码。

  
3 )编写 C / C ++  代码。这个代码将创建和实例化 JVM,并调用正确的 Java 方法。

  
4 )运行本机 C / C ++  应用程序。将运行应用程序以查看它是否正常工作。我们还将讨论一些用于处理常见错误的技巧。


       ☆ 第一步:编写Java代码
jnidemo.CCallJava.java


       ☆ 第二步:编译Java代码
  javac CCallJava.java


       ☆ 编写c代码
1 )开启VC

2 )新建一个Win32 Console Application工程,如果建立的是Win32 Application工程会报错[LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@ 16 ]

3 )在Source Files下新建文件cCallJava.c

4 )将jvm.lib加入到连接中,project -> Settings -> Link加入jvm.lib,同时配置Tools -> Directories -> Library files中加入jvm.lib目录,例如:
   C:/Program Files/Java/jdk1.
6.0 /lib

5 )配置Include路径,Tools -> Directories -> Include files加入java的include目录,例如:
   C:/Program Files/Java/jdk1.
6.0 /include
   C:/Program Files/Java/jdk1.
6.0 /include/win32
cCallJava.c


       ☆ 执行
1 )在编译的exe文件目录下新建jnidemo文件夹,把CCallJava.class拷贝到此目录下;

2 )执行exe文件
执行结果
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值