• java jni调用过程分析


    1.定义java类中的native方法,新建下面一个类

    public class NativeDemo {
    
        public static native void say();  //static的native方法
        
        public native void sayHello();  //实例的native方法,两者的处理不一样
        
        public static int number = 10;
        
        int a = 2;
        
        public void callThis(){
            System.out.println("c++ call java method");
        }
        
        public static void main(String[] args) {
            System.loadLibrary("NativeJni");
    //        NativeDemo.sayHello();
            new NativeDemo().sayHello();
            say();
        }
    }
    

    2.进入java命令行

       D:\project\workplatform.apps.demoLearnCenter\src\main\java>javah -help

    用法:javah [选项] <类>
    
    其中 [选项] 包括:
    
            -help                 输出此帮助消息并退出
            -classpath <路径>     用于装入类的路径
            -bootclasspath <路径> 用于装入引导类的路径
            -d <目录>             输出目录
            -o <文件>             输出文件(只能使用 -d 或 -o 中的一个)
            -jni                  生成 JNI样式的头文件(默认)
            -version              输出版本信息
            -verbose              启用详细输出
            -force                始终写入输出文件
    
    使用全限定名称指定 <类>(例
    如,java.lang.Object)。
    
    
    D:\project\workplatform.apps.demoLearnCenter\src\main\java>javap -help
    Usage: javap <options> <classes>...
    
    where options include:
       -c                        Disassemble the code
       -classpath <pathlist>     Specify where to find user class files
       -extdirs <dirs>           Override location of installed extensions
       -help                     Print this usage message
       -J<flag>                  Pass <flag> directly to the runtime system
       -l                        Print line number and local variable tables
       -public                   Show only public classes and members
       -protected                Show protected/public classes and members
       -package                  Show package/protected/public classes
                                 and members (default)
       -private                  Show all classes and members
       -s                        Print internal type signatures
       -bootclasspath <pathlist> Override location of class files loaded
                                 by the bootstrap class loader
       -verbose                  Print stack size, number of locals and args for methods
                                 If verifying, print reasons for failure
    



    3.在vc++新建一个dll的控制台工程

     


     

    4.在vc的工程里面导入刚才的那个NativeDemo.h的头文件,然后因为这个头文件需要引用jdk安装目录下的jni.h和jni_mt.h的两个头文件,从jdk的安装目录下的拷贝到工程里面

     


    4.编写NativeDemo.h的头文件定义的两个类的实现(这里需要吧jni.h include的时候要改为“”,而不是<>,因为jni.h是在当前工程里面

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

    #include "jni.h"
    /* Header for class NativeDemo */
    
    #ifndef _Included_NativeDemo
    #define _Included_NativeDemo
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     NativeDemo
     * Method:    say
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_NativeDemo_say
      (JNIEnv *, jclass);
    
    /*
     * Class:     NativeDemo
     * Method:    sayHello
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_NativeDemo_sayHello
      (JNIEnv *, jobject);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    c++源文件

       #include "NativeDemo.h"

    #include "jni.h"
    #include <iostream>
    using namespace std;
    
    JNIEXPORT void JNICALL Java_NativeDemo_say(JNIEnv * env, jclass jclazz)  //static的方法生成的两个参数是JNIEnv * env, jclass jclazz,第二个参数代表java的类的class实例
    {
    	jclass jclass_native = env->FindClass("NativeDemo"); //查找类的class对象,
    	jfieldID jfield_numberId = env->GetStaticFieldID(jclass_native,"number", "I"); //获得jclazz类的静态字段number,第三个参数代表静态变量的签名,java每种类型对应到一个签名串
    	jint jfield_number = env->GetStaticIntField(jclass_native, jfield_numberId);//获得jclazz类的静态变量的值
    	cout << jfield_number << endl; //打印静态变量的值
    
    }
    
    JNIEXPORT void JNICALL Java_NativeDemo_sayHello(JNIEnv *env, jobject jobj)//实例方法生成的第二个参数是jobject,代表某一个实例
    {
    	jclass clazz = env->GetObjectClass(jobj); //获得实例jobj的class对象
    	jfieldID jfield_numberId = env->GetFieldID(clazz,"a", "I"); //获得这个实例的a实例变量
    	jint jfield_value = env->GetIntField(jobj,jfield_numberId);  //获得这个实例的a实例变量的值
    	cout << jfield_value << endl;//打印这个实例的a实例变量的值
    }

    5.编译这个vc的工程,生成一个dll文件

     


     

    6.在我的电脑属性里面设置环境变量path增加这个dll的目录,因为java需要从path变量找到这个dll的目录

    7.打开eclipse,编写调用的main函数代码

    public class NativeDemo {   
     public static native void say();  //static的native方法
        
        public native void sayHello();  //实例的native方法,两者的处理不一样
        
        public static int number = 10;
        
        int a = 2;
        
        public void callThis(){
            System.out.println("c++ call java method");
        }
        
        public static void main(String[] args) {
            System.loadLibrary("NativeJni");
    //        NativeDemo.sayHello();
            new NativeDemo().sayHello();
            say();
        }
    }
    

     执行这个main函数,结果如下

     


     

    在java中需要使用System.loadLibrary("NativeJni");加载vc工程生成的dll文件,这里dll后缀不能加。

     



  • 相关阅读:
    剧集更新表
    Pyhton资源
    JAVA资源
    012 循环
    011 条件判断
    010 使用list和tuple
    009 字符串和编码
    007 Python基础
    python 内置函数
    python 获取当前运行的类名函数名inspect.stack()[1][3]
  • 原文地址:https://www.cnblogs.com/secbook/p/2655181.html
Copyright © 2020-2023  润新知