作者:唐老师,华清远见嵌入式学院讲师。

创建Java域的对象就是创建Java类的实例,再调用Java类的构造方法。

以Bitmap的构建为例,Bitmap中并没有Java对象创建的代码及外部能访问的构造方法,所以它的实例化必然是在JNI的c中实现的。

BitmapFactory.java中提供了得到Bitmap的方法,时序简化为:

BitmapFactory.java ->BitmapFactory.cpp ->

GraphicsJNI::createBitmap() [graphics.cpp]

GraphicsJNI::createBitmap()[graphics.cpp]的实现:

[cpp] view plaincopy
        1. jobjectGraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
        2. jbyteArray ninepatch, intdensity)
        3. {
        4.         SkASSERT(bitmap != NULL);
        5.         SkASSERT(NULL != bitmap->pixelRef());
        6.
        7.         jobject obj =env->AllocObject(gBitmap_class);
        8.         if (obj) {
        9.                 env->CallVoidMethod(obj,gBitmap_constructorMethodID,
        10.                 (jint)bitmap,isMutable, ninepatch, density);
        11.                 if (hasException(env)) {
        12.                         obj = NULL;
        13.                 }
        14.         }
        15.         return obj;
        16. }

而gBitmap_class的得到是通过:

2. gBitmap_class =(jclass)env->NewGlobalRef(c);
        3. //gBitmap_constructorMethodID是Bitmap的构造方法(方法名用”<init>”)的jmethodID:
        4. gBitmap_constructorMethodID= env->GetMethodID(gBitmap_class, "<init>",
        5. "(IZ[BI)V");

总结一下,c中如何访问Java对象的属性:
        1) 通过JNIEnv::FindClass()找到对应的jclass;
        2) 通过JNIEnv::GetMethodID()找到类的构造方法的jfieldID;
        3) 通过JNIEnv::AllocObject创建该类的对象;
        4) 通过JNIEnv::CallVoidMethod()调用Java对象的构造方法。

本地JNI对象的保存

c域中某次被调用生成的对象,在其他函数调用时是不可见的,虽然可以设置全局变量但那不是好的解决方式,Android中通常是在Java域中定义一个int型的变量,在c域生成对象的地方,与这个Java域的变量关联,在别的使用到的地方,在从这个变量中取值。

以JNICameraContext为例来说明:

JNICameraContext是android_hardware_camera.cpp中定义的类型,并会在cpp中生成对象,与Java中android.hardware.Camera的mNativeContext关联。

在注册native函数之前,c中就已经把Java域中的属性的jfieldID得到了。通过下列方法

2. jfieldID field = env->GetFieldID(clazz, " mNativeContext","I");

如果执行成功,把field保存到上面图中的fileds变量的context:jfieldID中。

生成cpp对象时,通过JNIEnv::SetIntField()设置为Java对象的属性

[cpp] view plaincopy
        1. static void android_hardware_Camera_native_setup(JNIEnv *env, jobjectthiz,
        2. jobject weak_this, jintcameraId)
        3. {
        4.         // …
        5.
        6.         // We use a weak reference sothe Camera object can be garbage collected.
        7.         // The reference is only used asa proxy for callbacks.
        8.         spcontext = new JNICameraContext(env, weak_this, clazz, camera);
        9.         // …
        10.         // 该处通过context.get()得到context对象的地址,保存到了Java中的mNativeContext属性里
        11.         env->SetIntField(thiz,fields.context, (int)context.get());
        12. }

而要使用时,又通过JNIEnv::GetIntField()获取Java对象的属性,并转化为JNICameraContext类型:

[cpp] view plaincopy
        1. JNICameraContext* context
=reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz,
fields.context));
        2. if (context != NULL) {
        3. // …
        4. }

总结一下,c++中生成的对象如何保存和使用:
        1) 通过JNIEnv::FindClass()找到对应的jclass;
        2) 通过JNIEnv::GetFieldID()找到类中属性的jfieldID;
        3) 某个调用过程中,生成cpp对象时,通过JNIEnv::SetIntField()设置为Java对象的属性;
        4) 另外的调用过程中,通过JNIEnv::GetIntField()获取Java对象的属性,再转化为真实的对象类型。

文章来源:华清远见嵌入式学院;原文地址:http://www.embedu.org/Column/Column881.htm

更多相关嵌入式免费资料查看华清远见讲师博文>>

本地C代码中创建Java对象的更多相关文章

  1. Java中JNI的使用详解第四篇:C/C++中创建Java对象和String字符串对象及对字符串的操作方法

    首先来看一下C/C++中怎么创建Java对象:在JNIEnv中有两种方法是用来创建Java对象的: 第一种方法: jobject  NewObject(jclass clazz  , jmethodI ...

  2. IntelliJ IDEA平台下JNI编程(五)—本地C代码创建Java对象及引用

    本文学习如何在C代码中创建Java对象和对象数组,前面我们学习了C代码中访问Java对象的属性和方法,其实在创建对象时本质上也就是调用构造函数,因此本文知识学习起来也很轻松.有了前面学习数组创建的方法 ...

  3. Java中创建实例化对象的几种方式

    Java中创建实例化对象有哪些方式? ①最常见的创建对象方法,使用new语句创建一个对象.②通过工厂方法返回对象,例:String s =String.valueOf().(工厂方法涉及到框架)③动用 ...

  4. Java中创建的对象多了,必然影响内存和性能

    1, Java中创建的对象多了,必然影响内存和性能,所以对象的创建越少越好,最后还要记得销毁.

  5. 在Android Native层中创建Java虚拟机实例

    前言 Android应用中JNI代码,是作为本地方法运行的.而大部分情况下,这些JNI方法均需要传递Dalvik虚拟机实例作为第一个参数.例如,你需要用虚拟机实例来创建jstring和其他的Java对 ...

  6. JNI_Z_08_创建Java对象

    1.步骤 : (1).获取 jclass (2).获取 构造函数的 method id (方法的名称始终为"<init>") (3).创建Java对象的两种方式: (3 ...

  7. 本地代码中使用Java对象

    通过使用合适的JNI函数,你可以创建Java对象,get.set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函数.JNI通过ID识别域和方 ...

  8. JavaScript中创建字典对象(dictionary)实例

    这篇文章主要介绍了JavaScript中创建字典对象(dictionary)实例,本文直接给出了实现的源码,并给出了使用示例,需要的朋友可以参考下 对于JavaScript来说,其自身的Array对象 ...

  9. 除了使用new关键字,还有什么方法可以创建Java对象呢?

    今天来盘点一下除了使用 "new" 关键字创建对象,还有什么方法可以创建Java对象呢? 因为是创建对象,所以这里ioc容器不在范围内 我们先看一下常用的new关键字创建 Clas ...

随机推荐

  1. DateTime还是DateTimeOffset?Now还是UtcNow?

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:新年第一篇文章,就来谈谈关于时间的简单技术问题:该用DateTime还是DateTim ...

  2. 在ASP.NET 5中读取配置文件

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 在ASP.NET 5中摒弃了之前配置文件的基础结构,引入了一个全新配置文件系统.今天推荐的文 ...

  3. linux系统定时任务

    crontab常用的几个命令如下 sudo crontab -l #显示所有的定时任务 sudo crontab -e #编辑任务 sudo crontab -r #删除所有的任务 编辑任务时的书写方 ...

  4. linux下vim配置以及一些常用的快捷键

    一些常用的vim编辑器快捷键: h」.「j」.「k」.「l」,分别控制光标左.下.上.右移一格. 按「ctrl」+「b」:屏幕往“后”移动一页. 按「ctrl」+「f」:屏幕往“前”移动一页. 按「c ...

  5. ITOO 第一个任务,新建界面

    最近我们已经接手了我们传承的的ITOO项目,虽然现在还是学习阶段,但是总是还有一些可以完成的东西的.通过需求学习阶段,对照给的原型,逐渐的我们发现了各种各样的问题,有的是根据个人性格有关,有的是对需求 ...

  6. hdu 1573 X问题 不互质的中国剩余定理

    X问题 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  7. css3 -- 网页字体

    1.@font-face规则 @font-face{ font-family:chunk; src:local('chunkFive'), url("chunkFive.ttf“) form ...

  8. js常用函数陆续总结

    1.each() 方法规定为每个匹配元素规定运行的函数. $.each(data,function(index,item){ sb.append(item.answerNum); } $(" ...

  9. android studio手动加入jar包

    点击启动AndroidStudio,启动后的界面如图所示. 复制你需要添加的jar,并将其黏贴到app— —src— —main— —libs文件夹下,可运行的AndroidStudio项目都有像这样 ...

  10. PLSQL看oracle中汉字显示乱码

    首先执行语句 select * from V$NLS_PARAMETERS  查看第一行中PARAMETER项中为NLS_LANGUAGE 对应的VALUE项中是否为SIMPLIFIED CHINES ...