Android中JNI高级应用 - 本地C代码中创建Java对象及本地JNI对象的保存

原创 2012年03月27日 23:53:00

++++++++++++++++++++++++++++++++++++++++++

本文系本站原创,欢迎转载! 转载请注明出处:

http://blog.csdn.net/mr_raptor/article/details/7401178

++++++++++++++++++++++++++++++++++++++++++


本地C代码中创建Java对象

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

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

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

BitmapFactory.java ->BitmapFactory.cpp -> GraphicsJNI::createBitmap()  [graphics.cpp]


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

jobjectGraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
                                  jbyteArray ninepatch, intdensity)
{
    SkASSERT(bitmap != NULL);
    SkASSERT(NULL != bitmap->pixelRef());

    jobject obj =env->AllocObject(gBitmap_class);
    if (obj) {
        env->CallVoidMethod(obj,gBitmap_constructorMethodID,
                            (jint)bitmap,isMutable, ninepatch, density);
        if (hasException(env)) {
            obj = NULL;
        }
    }
    return obj;
}

而gBitmap_class的得到是通过:

jclass c =env->FindClass("android/graphics/Bitmap");
gBitmap_class =(jclass)env->NewGlobalRef(c);
//gBitmap_constructorMethodID是Bitmap的构造方法(方法名用”<init>”)的jmethodID:
gBitmap_constructorMethodID= env->GetMethodID(gBitmap_class, "<init>",
                                           "(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得到了。通过下列方法

jclass clazz = env->FindClass("android/hardware/Camera ");
jfieldID field = env->GetFieldID(clazz, " mNativeContext","I");

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


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

static void android_hardware_Camera_native_setup(JNIEnv *env, jobjectthiz,
    jobject weak_this, jintcameraId)
{
    // …

    // We use a weak reference sothe Camera object can be garbage collected.
    // The reference is only used asa proxy for callbacks.
    sp<JNICameraContext>context = new JNICameraContext(env, weak_this, clazz, camera);
    // …
    // 该处通过context.get()得到context对象的地址,保存到了Java中的mNativeContext属性里
    env->SetIntField(thiz,fields.context, (int)context.get());
}

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

    JNICameraContext* context =reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));
    if (context != NULL) {
        // …
    }

总结一下,c++中生成的对象如何保存和使用:

1)   通过JNIEnv::FindClass()找到对应的jclass;

2)   通过JNIEnv::GetFieldID()找到类中属性的jfieldID;

3)   某个调用过程中,生成cpp对象时,通过JNIEnv::SetIntField()设置为Java对象的属性;

4)   另外的调用过程中,通过JNIEnv::GetIntField()获取Java对象的属性,再转化为真实的对象类型。


JNI完全详解:http://mindprod.com/jgloss/jni.html


++++++++++++++++++++++++++++++++++++++++++

本文系本站原创,欢迎转载! 转载请注明出处:

http://blog.csdn.net/mr_raptor/article/details/7401178

++++++++++++++++++++++++++++++++++++++++++


版权声明:本文为博主原创文章,未经博主允许不得转载。

JNI返回复杂对象之一

JNI返回复杂对象,对象里面的变量是Hashmap里面装ArrayList
  • cjj198561
  • cjj198561
  • 2014年08月18日 23:03
  • 7815

JNI学习积累之三 ---- 操作JNI函数以及复杂对象传递

本文原创,转载请注明出处:http://blog.csdn.net/qinjuning          在掌握了JNI函数的使用和相关类型的映射后,以及知晓何利用javah...
  • qinjuning
  • qinjuning
  • 2012年05月27日 21:19
  • 48835

[JNI]开发之旅(7)JNI函数中调用java对象的方法

在jni函数中我们不仅要对java对象的数据域进行访问,而且有时也需要调用java中类对象已经实现的方法。接下来我们对对象的方法调用,调用步骤与访问数据域相似。1.获得实例对应的class类 2.根据...
  • tsdfk1455
  • tsdfk1455
  • 2016年12月31日 20:51
  • 1336

java学习之JNI 学习四 创建JAVA对象

在c/c++本地代码中创建Java对象      1,使用函数NewObject可以用来创建JAVA对象;          GetMethodID 能够取得构造方法的jmethodID, 如果传入的...
  • v1v1wang
  • v1v1wang
  • 2010年04月08日 01:22
  • 8083

Android JNI反射调用Java构造方法、成员方法和静态方法

Android开发中一般讲Java接口调用放在APP层,但是如果想对外隐藏Java接口调用,应该怎么办呢?我们可以将接口调用放在JNI层,通过反射调用所需接口,之后打包成.so库,这样既可对外隐藏所有...
  • lb377463323
  • lb377463323
  • 2017年07月18日 14:12
  • 774

Android JNI中C和JAVA代码之间的互相调用

一、C语言代码回调Java方法 1. C代码回调Java方法的流程 (1) 找到java对应的Class 创建一个char*数组, 然后使用jni.h中提供的FindClass方法获取jclas...
  • quan648997767
  • quan648997767
  • 2017年03月23日 17:07
  • 1359

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

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

JNI和NDK编程(四)JNI调用Java方法的流程

JNI调用Java方法的流程JNI调用Java方法的流程是先通过类名找到类, 然后在根据方法名找到方法的id, 最后就可以调用这个方法了. 如果是调用Java的非静态方法, 那么需要构造出类的对象后才...
  • lj402159806
  • lj402159806
  • 2017年04月03日 18:21
  • 667

JNI学习笔记4——本地代码创建Java对象(包括javaString)

(一)在C/C++本地代码中创建JAVA对象1.java对象的创建(1)函数NewObject可以创建java对象(2)GetMethodID能够取得构造方法的jmethodID,如果传入的要取得的方...
  • jiben071
  • jiben071
  • 2010年11月26日 02:29
  • 3925

[JNI]开发之旅(6)JNI函数中访问java类中对象的属性

JNI函数的实现在c/c++中实现的,如果想访问java中定义的类对象的实例域需要三个步骤:1.通过GetObjectClass()函数获得该对象的类class,返回值是一个jclass; 2.调用...
  • tsdfk1455
  • tsdfk1455
  • 2016年12月25日 12:28
  • 827
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android中JNI高级应用 - 本地C代码中创建Java对象及本地JNI对象的保存
举报原因:
原因补充:

(最多只允许输入30个字)