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

创建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. hdu 4069 福州赛区网络赛I DLC ***

    再遇到一个DLC就刷个专题 #include <stdio.h> #include <string.h> #include <iostream> #include ...

  2. eclipse文本编码格式修改为UTF-8 (转)

    如果要使插件开发应用能有更好的国际化支持,能够最大程度的支持中文输出,则最好使 Java文件使用UTF-8编码.然而,Eclipse工作空间(workspace)的缺省字符编码是操作系统缺省的编码,简 ...

  3. 【hibernate 报错】No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer 【get和load的区别】

    报错: HTTP Status 500 - Could not write content: No serializer found for class org.hibernate.proxy.poj ...

  4. WINDOWS系统下四叶草CLOVER引导U盘制作

    一.所需软件1.下载BootDiskUtility链接:http://pan.baidu.com/s/1bwBFyu 密码:glyk 2.下载Clover r3330 USB链接:http://pan ...

  5. kylin的安装与配置

    我的环境: Cloudera Hadoop5.3.6 其中, Hadoop版本2.5.0 Hbase版本0.98.6 Hive版本0.13.1 使用的kylin版本:1.5.2.1 下载地址: htt ...

  6. 改变图片尺寸(python)

    for name in /图片路径; do convert -resize 256x256! $name $namedone

  7. hdu3448 01背包+dfs

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3448 Description 0/1 bag problem should sound f ...

  8. Java与.NET随笔

    .NET与Java,因这两种技术的相似性,总是会让人拿来做比较,并且总有人想让二者一分高下,最后得出孰优孰劣的结论.由于本人先用.NET,后转Java,现在.NET与Java二者并用,所以对二者间的差 ...

  9. wpf中手风琴控件Accordion编辑模板后控件不正常。

    昨天有个网友Accordion控件从sl迁移到wpf时候显示不正常.也是就没有效果. 我也是sl做的比较多,wpf玩的少,Accordion模板里触发器,状态组调了一早上都没达到满意效果, 无奈只有百 ...

  10. 8VC Venture Cup 2016 - Elimination Round

    在家补补题   模拟 A - Robot Sequence #include <bits/stdc++.h> char str[202]; void move(int &x, in ...