HotSpot笔记(六)——JNI原理

前言

JNI是JAVA标准平台中的一个重要功能,它弥补了JAVA的与平台无关这一重大优点的不足,在JAVA实现跨平台的同时,也能与其它语言(如C、C++)的动态库进行交互,给其它语言发挥优势的机会。
标准的java类库没有提供我们应用程序所需要的功能,通常这些功能是平台相关的(只能由其他语言编写);程序的某些部分对速度要求比较苛刻,我们选择用汇编或者c语言来实现并在java语言中调用他们;为了应用的安全性,会将一些复杂的逻辑和算法通过本地代码(C或C++)来实现,本地代码比字节码难以破解。

编写JNI

java代码

package com.bean.anotation.ownanotation;

public class JINTest {
    //普通成员
    private String addRess = "xian";
    //静态成员
    private static String name = "wellim";
    static {
        System.loadLibrary("libJNITest");
    }

    public static void loadMessage(String data){
        System.out.println(data);

    }
    //普通方法
    public void method(String data){
        loadMessage(data);
        loadMessage(addRess);
    }
    //静态方法
    public static void staticMethod(String data){
        loadMessage(data);
        loadMessage(name);
    }
    //java调用jni
    public static native String getJniData();

    public static native void callStaticMethod(int c);

    public static native void callStaticMethod(long i,String str);

    public native void callInstanceMethod(int i);

    public native void callInstanceMethod(String str,long i);
}

生成头文件(.h)

javac -h <directory> xxx.java命令生成对应jni头文件。头文件名为java文件包路径+文件名:com_bean_anotation_ownanotation_JINTest,内容就是java文件中native方法对应的C++函数声明。此文件供用户自己写的C、C++程序来引用并实现其中的函数。注:生成的.h文件需要includejni.h根据放入项目中相对位置修改导入路径,具体视情况变动。
在这里插入图片描述

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

#ifndef _Included_com_bean_anotation_ownanotation_JINTest
#define _Included_com_bean_anotation_ownanotation_JINTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_bean_anotation_ownanotation_JINTest
 * Method:    getJniData
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_bean_anotation_ownanotation_JINTest_getJniData
  (JNIEnv *, jclass);

/*
 * Class:     com_bean_anotation_ownanotation_JINTest
 * Method:    callStaticMethod
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_bean_anotation_ownanotation_JINTest_callStaticMethod__I
  (JNIEnv *, jclass, jint);

/*
 * Class:     com_bean_anotation_ownanotation_JINTest
 * Method:    callStaticMethod
 * Signature: (JLjava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_bean_anotation_ownanotation_JINTest_callStaticMethod__JLjava_lang_String_2
  (JNIEnv *, jclass, jlong, jstring);

/*
 * Class:     com_bean_anotation_ownanotation_JINTest
 * Method:    callInstanceMethod
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_bean_anotation_ownanotation_JINTest_callInstanceMethod__I
  (JNIEnv *, jobject, jint);

/*
 * Class:     com_bean_anotation_ownanotation_JINTest
 * Method:    callInstanceMethod
 * Signature: (Ljava/lang/String;J)V
 */
JNIEXPORT void JNICALL Java_com_bean_anotation_ownanotation_JINTest_callInstanceMethod__Ljava_lang_String_2J
  (JNIEnv *, jobject, jstring, jlong);

#ifdef __cplusplus
}
#endif
#endif

编写cpp

自己编写的c、c++程序调用java方法和jni方法的具体实现。代码里的函数实现一定要和.h文件中函数名称一致。

//
// Created by success on 2021/7/26.
//
#include "../jni/com_bean_anotation_ownanotation_JINTest.h"
#include <iostream>
#include <stdio.h>

//java调用jni方法
JNIEXPORT jstring JNICALL Java_com_bean_anotation_ownanotation_JINTest_getJniData
        (JNIEnv * env, jclass jcls){
    return env->NewStringUTF("c语言数据");
}

/*
 * Class:     com_bean_anotation_ownanotation_JINTest_callStaticMethod
 * Method:    callStaticMethod
 * Signature: (I)V
 */
//调用静态方法 和修改成员变量
JNIEXPORT void JNICALL Java_com_bean_anotation_ownanotation_JINTest_callStaticMethod__I
(JNIEnv * env, jclass jclassess, jint i){
//找到相关的类 注意路径是带反斜杆  不是带.
jclass cls_First = env->FindClass("com/bean/anotation/ownanotation/JINTest");
if(cls_First == NULL){
return;
}

/**
方法参数:类名,方法名,方法签名
*/
//找到对应的方法  注意签名后面有冒号
jmethodID mtd_static_method = env->GetStaticMethodID(cls_First,"staticMethod","(Ljava/lang/String;)V");
if(mtd_static_method == NULL){
return;
}

//修改java中静态字段的值 获取成员变量  注意签名后面有冒号
jfieldID file_name = env->GetStaticFieldID(cls_First,"name","Ljava/lang/String;");
if(file_name == NULL){
return;
}
//定义静态字段的值
jstring name = env->NewStringUTF("西西");
//对成员变量设置值
env ->SetStaticObjectField(cls_First,file_name,name);

jstring data = env->NewStringUTF("call static method");
if(data == NULL){
return;
}

//调用java层静态方法
env ->CallStaticVoidMethod(cls_First,mtd_static_method,data);

//删除引用
env->DeleteLocalRef(cls_First);
env->DeleteLocalRef(name);
env->DeleteLocalRef(data);

}


/*
 * Class:     com_bean_anotation_ownanotation_JINTest
 * Method:    callInstanceMethod
 * Signature: (I)V
 */
//调用java实例方法 和修改实例变量
JNIEXPORT void JNICALL Java_com_bean_anotation_ownanotation_JINTest_callInstanceMethod__I
(JNIEnv *env, jobject jobj, jint i){

//找到相关的类
jclass cls_First = env->FindClass("com/bean/anotation/ownanotation/JINTest");
if(cls_First == NULL){
return;
}

//找到对应的方法
jmethodID mtd_method = env->GetMethodID(cls_First,"method","(Ljava/lang/String;)V");
if(mtd_method == NULL){
return;
}

//找到对应的构造方法
jmethodID mtd_construct = env->GetMethodID(cls_First,"<init>","()V");
if(mtd_construct == NULL){
return;
}


jfieldID fld_address = env->GetFieldID(cls_First,"addRess","Ljava/lang/String;");
if(fld_address == NULL){
return;
}

jstring address = env->NewStringUTF("上海&苏州");
if(address == NULL){
return;
}

//创建相应的对象
jobject oFirst = env->NewObject(cls_First,mtd_construct,NULL);
if(oFirst == NULL){
return;
}

//注意此时的对象  应该是jobject对象 非jclass对象
env->SetObjectField(oFirst,fld_address,address);

jstring message = env->NewStringUTF("call instance method");

//调用java层实例方法  注意此时的对象  应该是jobject对象 非jclass对象
env->CallVoidMethod(oFirst,mtd_method,message);

//清除对象的引用
env->DeleteLocalRef(message);
env->DeleteLocalRef(cls_First);
env->DeleteLocalRef(oFirst);
env->DeleteLocalRef(address);

}

编译生成dll库

JNI调用的核心实现在在动态库libjvm.dll(Linux上是libjvm.so),而该动态库源码核心在jni.h,该头文件又依赖jni_md.h,所以需要把他们都拷贝到项目中
在这里插入图片描述

把dll导入到java项目依赖

在这里插入图片描述

调用

从结果看native方法被调用,变量值被修改。

public static void main(String[] args) {
        //FiledTest ft = new FiledTest();
        JINTest nat = new JINTest();
        nat.callInstanceMethod(1);
        JINTest.callStaticMethod(32);
        System.out.println(JINTest.getJniData());
        System.out.println("shs");
    }
/** call instance method
	上海&苏州
	call static method
	西西
	c语言数据
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值