JNI开发系列④C语言调用构造方法

接续上篇JNI开发系列③C语言调用Java字段与方法

前情提要

Java调用C方法很简单 , 只需要编写native方法即可 , 通过C去调用Java的字段与方法 , 则需要比较复杂的操作 , 上篇中介绍了 , C调用的Java字段与方法的几个套路:

步骤一 、 得到jclass, 字节码对象 , 如果是static native修饰 , 则函数会以jclass类型传入 , 非静态则需要得到jclass类型 。

步骤二 、得到字段或方法ID , 区分静态字段与对象字段 , 静态字段或方法调用(env)->GetStaticFieldID,(env)->GetMethodID函数得到ID , 对象字段调用(env)->GetFieldID,(env)->GetStaticMethodID得到ID 。 可以得到一个套路 , 静态修饰的 , 则调用static标识的函数 , 非静态的则调用常规函数 。

步骤三 、 取得字段的值或调用方法 , 需要注意的是, 得到字段的值与调用方法 , 都有类型的区分 。引用类型则使用GetObjectField, CallStaticObjectMethod, 其他类型 , 则有对于的jxxx类型对应 。套路简写:Get<Type>Field, GetStatic<Type>Field, Call<Type>Method, CallStatic<Type>Method 。

步骤四 、 类型转换 , 如果是Java引用类型 , 则需要进行类型转换

C 调用Java对象的构造方法

C调用Java的构造方法与调用普通方法略有不同 , 其不同之处在于方法名称上 , 普通方法直接使用方法名 , 构造方法则不是使用类名 , 而使用一个固定写法<init>

java code  使用C语言创建一个Date对象,获取时间戳

private native long accessConstructorMethod() ;

public static void main(String[] args) {
     long timeLong = jni.accessConstructorMethod() ;
         
     SimpleDateFormat sdf = new SimpleDateFormat();
     sdf.applyPattern("yyyy-MM-dd  HH:mm:ss") ;
     String dateString = sdf.format(new Date(timeLong)) ;
}

使用C创建Java对象 , 并调用方法

/*访问java对象的构造方法*/
JNIEXPORT jlong JNICALL Java_com_zeno_jni_HelloJni_accessConstructorMethod
(JNIEnv *env, jobject jobj) {

    // 找到Date的jclass
    jclass dateCls = (*env)->FindClass(env, "java/util/Date");

    // 得到构造方法id
    jmethodID dateConstructMid = (*env)->GetMethodID(env, dateCls, "<init>", "()V");

    // 创建Date对象
    jobject dateObj = (*env)->NewObject(env, dateCls, dateConstructMid);

    // 得到getTime方法ID
    jmethodID getTimeMid = (*env)->GetMethodID(env, dateCls, "getTime", "()J");

    // 调用getTime方法
    jlong timeLong = (*env)->CallLongMethod(env, dateObj, getTimeMid);

    printf("new Date().getTime : %lld\n", timeLong);

    return timeLong;
}

Tips:

C实例化Java对象的时候 , 首先需要找到对象的class , 以全类名表示 , ./代替 (java.util.Date --> Java/util/Date)。Java的构造函数名称为固定的<init>名称 , 通过NewObject()函数来创建Java对象 。需要注意的是签名 , 我们可以通过javap -s -p来获取签名 。常见签名如下:

数据类型 签名
boolean Z
byte B
char C
short S
int I
long L
float F
double D
void V
object L开头,然后以/分隔的完整类型,后面再加;例如:String类型签名 Ljava/lang/String
Array 以[开头,再加上数组元素的签名。例如int[]的签名是 [I , int[][]是[[I

C与Java的字符转换

在开发中 , 我们常常都会遇到字符编码问题 , web开发的时候 , 时常需要指定网页的编码 , 国内一般常用GBK与UTF-8 ,这两种编码格式 。 我们在开发项目的时候 , 也会指定项目的文件编码 , 因为不同文件编码对于汉字的支持与处理不同 , GBK采用的是一字节和双字节编码 , 而UTF-8则采用的是 , 一至四个字节编码 , 单个字符使用一个直接表示 , 汉字则使用四个字节表示 。

java code

private native String cTransformChar(String str) ;

public static void main(String[] args) {
    HelloJNI jni = new HelloJNI() ;
    System.out.println(jni.cTransformChar("住"));
}

C处理字符编码

/*C的字符转换*/

JNIEXPORT jstring JNICALL Java_com_zeno_jni_HelloJNI_cTransformChar
(JNIEnv *env, jobject jobj,jstring jStr) {

    // 将jstring转换成c字符指针
    char *cStr = (*env)->GetStringUTFChars(env, jStr, NULL);

    jsize js = (*env)->GetStringLength(env, jStr);


    printf("传进来的值size :  %d\n", js);
    printf("传进来的值 :  %s\n", cStr);

    char destBuffer[50] = "非我 and 小九";

    // 得到String类
    jclass stringCls = (*env)->FindClass(env, "java/lang/String");

    // 得到构造方法的ID
    jmethodID stringConstructMid = (*env)->GetMethodID(env, stringCls, "<init>", "([BLjava/lang/String;)V");

    /*
    使用到的Java构造方法
    String(byte[] bytes, String charsetName) 
     通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
    */

    // 构建一个bytes数组
    jbyteArray strBytes = (*env)->NewByteArray(env, 50);

    // 设置字符数组
    (*env)->SetByteArrayRegion(env, strBytes, 0, strlen(destBuffer), destBuffer);

    // 构建字符编码
    jstring charSetName = (*env)->NewStringUTF(env, "GBK"); 
    // 创建String类的对象
    jstring transformStr = (*env)->NewObject(env, stringCls, stringConstructMid, strBytes, charSetName);

    return transformStr;
}

Tips

如果是使用的eclipse控制台输出 , 一定要注意控制台的字符编码 , 如果编码不统一 , 控制台就会输出乱码 ,如:如果要输出的字符是UTF-8而控制台是GB2312 , 则会输出乱码 。 如果出现乱码 , 可以将字符写入到文件中 , 看看是否会乱码 ,如果乱码 ,可以使用notepad++看一下文件的编码 , 如果编码一致 , 则会显示正常 。

结语

这几天公司产品上线 , 有点忙碌 , 没多少时间写文章 , 今天恢复写文章的进度。昨天和一个创业公司的CEO聊了聊 , 发现自己欠缺的东西还有很多很多 , 对于产品的架构 , 如何从0到1 , 将想法转换为产品 , 没有一个完整的产品思路 ,也没有产品经理的思维能力,有的只是对界面的吹毛求疵 , 对部分功能的自以为是 。任何行业 , 没有深入进去 , 看的永远只是表面 , 都是别人玩剩下的 。

刻意练习技术 , 时刻思考产品 。

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

推荐阅读更多精彩内容

  • 现在,你知道了如何通过JNI来访问JVM中的基本类型数据和字符串、数组这样的引用类型数据,下一步就是学习怎么样和J...
    738bc070cd74阅读 869评论 0 1
  • 接续上篇JNI开发系列②.h头文件分析 前情提要 在前面 , 我们已经熟悉了JNI的开发流程 , .h头文件的分析...
    逝我阅读 3,648评论 3 13
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,559评论 18 399
  • D24~3月17日 我有健康的身体,有工作有朋友,有爱我的老公,有一双可爱的儿女,父母平安健康。 感恩!感恩!感恩...
    sky冬日暖洋洋阅读 124评论 0 0
  • 《干法》和《活法》两书是日本的"经营之圣"稻盛和夫所写,他把企业经营上升为哲学思想,把人生活出一个新的高度,成就更...
    孙国飞扬阅读 361评论 0 8