本地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 ...
随机推荐
- W-数据库基础
数据库系统由三部分组成:数据库(DB).数据库管理系统(DBMS)和数据库应用系统 数据加是用来存储数据的,里面存储两大类数据:用户数据及系统数据/数据字典,具体为系统中的用户以及用户孤权限,各种统计 ...
- GitHub上史上最全的Android开源项目分类汇总 (转)
GitHub上史上最全的Android开源项目分类汇总 标签: github android 开源 | 发表时间:2014-11-23 23:00 | 作者:u013149325 分享到: 出处:ht ...
- Android之Adapter用法总结-(转)
Android之Adapter用法总结 1.概念 Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带.在常见的View(List View,Grid Vie ...
- 在Salesforce中添加Workflow Rule
在Salesforce中可以添加Workflow Rule来执行特定的动作,比如说:当Object的某个字段发生变化时,根据变化的值去修改其他field,和Trigger的功能很类似,不过Trigge ...
- struct 类型重定义
类型定义的那个头文件只需要在功能源文件里#include 开始在主函数源文件里也#include,所以出现了重定义
- Java学习笔记(一)——HelloWorld
一.安装JDK 1.下载链接: http://www.oracle.com/technetwork/java/javase/downloads/index.html 2.直接安装,不能有中文路径 3. ...
- TortoiseSVN菜单项功能说明
TortoiseSVN是windows下其中一个非常优秀的SVN客户端工具.通过使用它,我们可以可视化的管理我们的版本库.不过由于它只是一个客户端,所以它不能对版本库进行权限管理. TortoiseS ...
- SpringMyBatis解析3-MapperFactoryBean
在使用mybatis的时候,我们获取dao的方式一般是这样: SqlSession session=sessionFactory.openSession(); PersonDao personDao= ...
- java.lang.instrument使用
Java在1.5引入java.lang.instrument,你可以由此实现一个Javaagent,通过此agent来修改类的字节码即改变一个类. 程序启动之时启动代理(pre-main) 通过jav ...
- Oracle PL/SQL设置快捷键的方法
pl sql默认设置不是很方便,最近搜罗了一下网上关于PLSQL的一些常用快捷键配置,主要是方便以后自个使用 1.登录后默认自动选中My Objects 默认情况下,PLSQL Developer ...