本地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]的实现:
[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对象的更多相关文章
- Java中JNI的使用详解第四篇:C/C++中创建Java对象和String字符串对象及对字符串的操作方法
首先来看一下C/C++中怎么创建Java对象:在JNIEnv中有两种方法是用来创建Java对象的: 第一种方法: jobject NewObject(jclass clazz , jmethodI ...
- IntelliJ IDEA平台下JNI编程(五)—本地C代码创建Java对象及引用
本文学习如何在C代码中创建Java对象和对象数组,前面我们学习了C代码中访问Java对象的属性和方法,其实在创建对象时本质上也就是调用构造函数,因此本文知识学习起来也很轻松.有了前面学习数组创建的方法 ...
- Java中创建实例化对象的几种方式
Java中创建实例化对象有哪些方式? ①最常见的创建对象方法,使用new语句创建一个对象.②通过工厂方法返回对象,例:String s =String.valueOf().(工厂方法涉及到框架)③动用 ...
- Java中创建的对象多了,必然影响内存和性能
1, Java中创建的对象多了,必然影响内存和性能,所以对象的创建越少越好,最后还要记得销毁.
- 在Android Native层中创建Java虚拟机实例
前言 Android应用中JNI代码,是作为本地方法运行的.而大部分情况下,这些JNI方法均需要传递Dalvik虚拟机实例作为第一个参数.例如,你需要用虚拟机实例来创建jstring和其他的Java对 ...
- JNI_Z_08_创建Java对象
1.步骤 : (1).获取 jclass (2).获取 构造函数的 method id (方法的名称始终为"<init>") (3).创建Java对象的两种方式: (3 ...
- 本地代码中使用Java对象
通过使用合适的JNI函数,你可以创建Java对象,get.set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函数.JNI通过ID识别域和方 ...
- JavaScript中创建字典对象(dictionary)实例
这篇文章主要介绍了JavaScript中创建字典对象(dictionary)实例,本文直接给出了实现的源码,并给出了使用示例,需要的朋友可以参考下 对于JavaScript来说,其自身的Array对象 ...
- 除了使用new关键字,还有什么方法可以创建Java对象呢?
今天来盘点一下除了使用 "new" 关键字创建对象,还有什么方法可以创建Java对象呢? 因为是创建对象,所以这里ioc容器不在范围内 我们先看一下常用的new关键字创建 Clas ...
随机推荐
- 使用html5 canvas绘制圆形或弧线
注意:本文属于<html5 Canvas绘制图形入门详解>系列文章中的一部分.如果你是html5初学者,仅仅阅读本文,可能无法较深入的理解canvas,甚至无法顺畅地通读本文.请点击上述链 ...
- Code Review for SSIS package
以下是我对SSIS包进行code review的一些建议,如果有其他更好的方案欢迎拍砖. A. 查看是否使用了最优的解决方案 1. 最优的结构视图 2. 解决方案,包,任务,组建,参数的命名使用了易读 ...
- 攻城狮在路上(壹) Hibernate(二)--- 第一个hibernate程序
1.直接通过JDBC API持久化实体域对象: A.java.sql常用接口和类: DriverManager:驱动程序管理器,负责创建数据库连接. Connection:代表数据库连接. State ...
- Solr入门之(6)配置文件solrconfig.xml
solrconfig.xml包含了用于配置自身行为的绝大部分参数,其作用范围是当前core.该文件位于${solr_home}/solr/core1/conf/下. 参数列表概览: A.lib B.d ...
- ereg/eregi报错处理办法
ereg()函数和eregi()函数用法相同,不同之处在与ereg()区分大小写,eregi()不区分大小写 在php5.3以上的版本将不再支持eregi()和ereg()函数 处理办法: 正则函数处 ...
- [Unity3D插件]2dtoolkit系列二 动画精灵的创建以及背景图的无限滚动
经过昨天2dtoolkit系列教程一的推出,感觉对新手还有有一定的启发作用,引导学习使用unity 2dToolKit插件的使用过程,今天继续系列二——动画精灵的创建,以及背景图的无限循环滚动,在群里 ...
- [荐]jquery插件开发入门
http://www.cnblogs.com/Wayou/p/jquery_plugin_tutorial.html $.fn.myPlugin = function() { //在这里面,this指 ...
- 命令模式/command模式/行为型模式
举个栗子 指挥官向士兵下达命令,士兵执行 实现代码如下: class Soldier { public void exe() { System.out.println("执行命令" ...
- Serializable序列化对象
Serializable序列化对象发送: Intent intent = new Intent(); intent.setClass(mContext, HomeDetailReportActivit ...
- Oracle资源
ORACLE 10g下载地址 oracle 下载还需要用户名我自己注册了个方便大家使用下载 user:1603869780@qq.compass:qwe123QWE现在直接点击不能下载了 要经过ora ...