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

创建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. 攻城狮在路上(叁)Linux(十七)--- linux磁盘与文件管理概述

    一.复习知识点: 1.扇区是最小的物理存储单位,大小为512bytes. 2.扇区组成一个圆,成为柱面,柱面是分区的最小单位. 3.第一个扇区很重要,因为包含了MBR(446字节)和分区表(64字节) ...

  2. Solr入门之(5)配置文件schema.xml

    该配置文件中的标签:<fileTypes>.<fields>.<uniqueKey>.<copyField> fieldType说明 标签types中定 ...

  3. B树算法与实现 (C语言实现)

    B树的定义 假设B树的度为t(t>=2),则B树满足如下要求:(参考算法导论) (1)  每个非根节点至少包含t-1个关键字,t个指向子节点的指针:至多包含2t-1个关键字,2t个指向子女的指针 ...

  4. 动软MySQL存储过程模板

    <#@ template language="c#" HostSpecific="True" #><#@ output extension= ...

  5. [Unity3D]上海某大型游戏公司的基础面试题

    一个小老乡跟我聊到去上海某大公司的基础面试题,面试结果不尽如人意,但还是分享了下面试的试题,刚刚第一次录制视频,给某人讲课,我感觉讲的还算比较耐心,但发现一些新手入门学习的弊端,可能是很普遍的现象,这 ...

  6. PHP 部署发布接口

    环境前提:电脑已安装wamp ① 在\wamp\bin\apache\apache2.4.9\conf\httpd.conf文件中, 修改 DocumentRoot 为当前项目路径,例如 Docume ...

  7. HDU 5213 Lucky 莫队+容斥

    Lucky Problem Description WLD is always very lucky.His secret is a lucky number K.k is a fixed odd n ...

  8. 软件开发中的完整测试所包括的环节UT、IT、ST、UAT

    软件开发中的完成测试环境所包括的环节包括:UT.IT.ST.UAT UT = Unit Test 单元测试 IT = System Integration Test 集成测试ST = System T ...

  9. android应用程序如何调用支付宝接口

    最近在做一个关于购物商城的项目,项目里面付款这块我选的是调用支付宝的接口,因为用的人比较多. 在网上搜索了以下,有很多这方面的教程,但大部分教程过于陈旧,而且描述的过于简单.而且支付宝提供的接口一直在 ...

  10. Swift3.0语言教程使用编码创建和初始化字符串

    Swift3.0语言教程使用编码创建和初始化字符串 使用编码创建和初始化字符串 创建和初始化字符串除了可以使用上文中提到的方法外,还可以使用init(coder:)方法,此方法一般不常使用,其语法形式 ...