JNI 学习笔记(二)-- JNI访问Java中各方法

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。我的CSDN地址:http://blog.csdn.net/urrjdg
本文CSDN地址:http://blog.csdn.net/urrjdg/article/details/78158959

CSDN 和 简书 同步更新
看目录去CSDN

1. JNI 访问 java 中的 非静态方法

package com.zeking.jni;

import java.util.Random;


public class JniTest02 {

    public native void accessMethod();
    
    int getRandom(int max){
        return new Random().nextInt(max);
    }
    
    static{
        System.loadLibrary("lsn02");
    }
    
    public static void main(String[] args) {
        JniTest02 jniTest02 = new JniTest02();
        jniTest02.accessMethod();
    }
}
#include "com_zeking_jni_JniTest02.h"

/*
* Class:     com_zeking_jni_JniTest02
* Method:    accessMethod
* Signature: ()V
*/
// JN访问 java 中的 非静态方法
JNIEXPORT void JNICALL Java_com_zeking_jni_JniTest02_accessMethod
(JNIEnv * env, jobject  jobj){

    jclass jclz = (*env)->GetObjectClass(env, jobj);

    jmethodID jmid = (*env)->GetMethodID(env, jclz, "getRandom", "(I)I");

    jint jint = (*env)->CallIntMethod(env, jobj, jmid, 200);

    printf("c random: %d\n",jint);

}

2. JNI 访问Java 中的静态方法

package com.zeking.jni;

import java.util.Random;
import java.util.UUID;


public class JniTest02 {

    public native void accessStaticMethod(); 
    
    public static String getRandomUUId(){
        return UUID.randomUUID().toString();
    }
    
    static{
        System.loadLibrary("lsn02");
    }
    
    public static void main(String[] args) {
        JniTest02 jniTest02 = new JniTest02();
        jniTest02.accessStaticMethod();
    }   
}
/*
* Class:     com_zeking_jni_JniTest02
* Method:    accessStaticMethod
* Signature: ()V
*/
// JN访问 java 中的 非静态方法
JNIEXPORT void JNICALL Java_com_zeking_jni_JniTest02_accessStaticMethod
(JNIEnv *env, jobject jobj){
    
    jclass jclz = (*env)->GetObjectClass(env, jobj);

    jmethodID jmid = (*env)->GetStaticMethodID(env, jclz, "getRandomUUId", "()Ljava/lang/String;");

    jstring uuid = (*env)->CallStaticIntMethod(env, jclz, jmid);

    char * uuid_c = (*env)->GetStringUTFChars(env, uuid, NULL);

    char filename[100];
    sprintf(filename,"D://%s.txt",uuid_c);

    FILE *fp = fopen(filename, "w");

    fputs("I am Zeking", fp);

    fclose(fp);

    printf("文件写入成功\n");
}

3. JNI 访问java构造方法

package com.zeking.jni;

import java.util.Date;
import java.util.Random;
import java.util.UUID;


public class JniTest02 {

    static{
        System.loadLibrary("lsn02");
    }
    
    public native Date accessConstructor();
    
    public static void main(String[] args) {
        JniTest02 jniTest02 = new JniTest02();
        jniTest02.accessConstructor();
    }   
}
/*
* Class:     com_zeking_jni_JniTest02
* Method:    accessConstructor
* Signature: ()Ljava/util/Date;
*/
// 访问构造方法
JNIEXPORT jobject JNICALL Java_com_zeking_jni_JniTest02_accessConstructor
(JNIEnv * env, jobject jobj){
    // 通过类的路径来从JVM 里面找到对应的类
    jclass jclz = (*env)->FindClass(env, "java/util/Date");

    // jmethodid     <init> 构造方法
    jmethodID jmid = (*env)->GetMethodID(env, jclz, "<init>", "()V");

    // 调用 newObject 实例化Date 对象,返回值是一个jobjcct
    // 为什么是jobject 不是  Date,因为 在jni 里面 数据的类型对应的关系就是将所有的 引用类型全部转换为jobjct
    jobject date_obj = (*env)->NewObject(env, jclz, jmid);

    // 得到对应对象的方法,前提是,我们访问了相关对象的构造函数创建了这个对象
    jmethodID time_mid = (*env)->GetMethodID(env, jclz, "getTime", "()J");

    jlong time = (*env)->CallLongMethod(env, date_obj, time_mid);

    printf("time : %lld \n", time);

    return date_obj;
}

4. 中文

这里写图片描述
package com.zeking.jni;

import java.util.Date;
import java.util.Random;
import java.util.UUID;


public class JniTest02 {

    public native String chineseChars(String str);
    
    static{
        System.loadLibrary("lsn02");
    }
    
    public native Date accessConstructor();
    
    public static void main(String[] args) {
        JniTest02 jniTest02 = new JniTest02();
        jniTest02.chineseChars("测试中文");
    }   
}
#include "stdafx.h"
#include "com_zeking_jni_JniTest02.h"
#include <Windows.h>
#include <string.h>

// 乱码
// java使用的是
// utf - 16 16bit  2个字节

// JNI 里面使用的是
// utf - 8   unicode  可变字节的方式   英文 1个字节    ,中文 3个字节

// C C++
// ascii编码, 中文 的编码方式  GB2312  编码,中文 2个 字节
/*
* Class:     com_zeking_jni_JniTest02
* Method:    chineseChars
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
// 中文
JNIEXPORT jstring JNICALL Java_com_zeking_jni_JniTest02_chineseChars
(JNIEnv * env, jobject jobj, jstring in){
    // 方法一
    jboolean iscp;
    // char * c_str = (*env)->GetStringChars(env, in, NULL);
    // JVM会重新开辟一个内存然后存储 in的值
    char * c_str = (*env)->GetStringChars(env, in, &iscp);
    if (iscp == JNI_TRUE) // 传&iscp 是为了获取或者得到 它的返回值,判断是否会开辟一个新的内存(这个新内存放着一样的stirng值)给 c 来使用
    {
        printf("is copy: JNI_TRUE\n");
    }
    else if (iscp == JNI_FALSE)
    {
        printf("is copy: JNI_FALSE\n");
    }
    // 得到字符串的长度
    int length = (*env)->GetStringLength(env, in);
    const jchar * jcstr = (*env)->GetStringChars(env, in, NULL);
    // 有可能内存不够,判空
    if (jcstr == NULL) {
        return NULL;
    }
    //jchar -> char
    char * rtn = (char *)malloc(sizeof(char) *2 * length + 3);
    memset(rtn, 0, sizeof(char) * 2 * length + 3);
    int size = 0;
    // 就是当我们得到的jcstr指针变量所指的内容全部复制到 对应的指针里面来rtn(这个函数只有window环境才有)
    size = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)jcstr, length, rtn, sizeof(char) * 2*length + 3, NULL, NULL);
    /*if (size <= 0)
    {
        printf("size: 0 \n", rtn);
        return NULL;
    }*/
    
    printf("string: %s\n", rtn);
    
    if (rtn != NULL) {
        free(rtn);
        rtn = NULL;
    }
    (*env)->ReleaseStringChars(env, in, c_str);// JVM 使用。通知JVM c_str 所指的空间(这个内存是jvm另外开辟的一个内存,所以要释放)可以释放了
    
    
    return NULL;

    // 方法二   
    
    // String 类中构造函数,讲byte[] 转为对应编码的字符串
    //public String(byte bytes[], Charset charset) {
    //    this(bytes, 0, bytes.length, charset);
    //}
    
    //char *c_str = "中文中文中文";
    //jclass str_cls = (*env)->FindClass(env, "java/lang/String");
    //jmethodID jmid = (*env)->GetMethodID(env, str_cls, "<init>", "([BLjava/lang/String;)V");
    //
    ////jstring -> jbyteArray
    //jbyteArray bytes = (*env)->NewByteArray(env, strlen(c_str));
    //// 将Char * 赋值到 bytes
    //(*env)->SetByteArrayRegion(env, bytes, 0, strlen(c_str), c_str);
    //jstring charsetName = (*env)->NewStringUTF(env, "GB2312");

    //return (*env)->NewObject(env, str_cls, jmid, bytes, charsetName);

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,333评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,812评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,016评论 0 246
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,293评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,650评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,788评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,003评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,741评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,462评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,681评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,168评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,528评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,169评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,119评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,902评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,846评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,719评论 2 274

推荐阅读更多精彩内容