首页 文章 精选 留言 我的

精选列表

搜索[memory],共7514篇文章
优秀的个人博客,低调大师

Erupt 1.14.1 已发布,AI 能力全面升级,增加 🦞 能力,支持 MCP、SKILL、MEMORY

Erupt 低代码 + AI 全开源 Erupt 是一个低代码全栈类框架,它使用Java 注解动态构建页面,及增、删、改、查、权限控制等功能。 零前端代码、零 CURD、自动建表,仅需一个类文件+简洁的注解配置,快速开发企业级 Admin 管理后台。 🦞 AI & CLAW 🦞 EruptAI Claw 通过自然语言直接驱动服务器,操作注解驱动的数据与业务——像与同事对话一样简单 将大模型能力无缝融入低代码开发,让 AI 赋能每一个业务场景 本次更新内容 🐞 修复 Date 类型修饰 Erupt 对象时默认使用 UTC 时间的问题 🐞 修复编辑场景下 @OnChange 注解导致后端联动值覆盖数据库原始数据的问题 🐞 修复 @JoinColumn 注解 referencedColumnName 配置不生效的问题,感谢 jx2047 贡献的代码 🧩 时间字段导出 Excel 时,自动根据用户当前语言环境格式化时间 #98d579 🧩 erupt-flow 新增多种审批方式:由其他节点分配审批人、发起人自选审批人、分管领导审批 🧩 erupt-flow 新增办理节点,优化流程画布交互体验与功能排版 🧩 重构时间格式处理逻辑,统一采用 ISO 8601(yyyy-MM-dd'T'HH🇲🇲ss.SSS)进行交互,返回时间自动跟随浏览器语言环境格式化,对国际化场景更加友好 🦞 开源 eurpt-ai-claw 模块,可通过 AI 操作任意 Erupt 数据,支持 Skill、File、Shell 调用等能力 🌟 Spring Boot 版本升级至 3.5.13 🌟 eruptUser 新增分管组织字段,并新增 e_upms_user_org_division 表用于存储分管组织数据 🌟 erupt-ai 增加安全策略,AI 对话能力不再开放给所有用户,后端 API 使用菜单权限隔离此入口 🌟 erupt-ai 完全重构:前端基于 Angular 重新构建,后端使用 Langchain4j 重写,AI Tool 声明改为方法级 🌟 erupt-ai LLM 新增 Claude、Gemini、Doubao 支持 🌟 erupt-ai 支持调用外部 MCP Server 🌟 erupt-ai 支持通过 ReAct 模式智能调度已注册的 AI 工具,并展示推理过程 🌟 新增 skill 文件,方便 AI 与 erupt 更好的交互:commands 🌟 开源 erupt-vote 投票插件,感谢 @PPLINGHUFEI 的贡献 🌟 EruptMenu 菜单数据统一以英文存储,前端页面自动翻译为对应语言展示 项目官网:www.erupt.xyz @Erupt( name = "简单的例子", power = @Power(importable = true, export = true) ) @Table(name = "t_simple") //数据库表名 @Entity public class Simple extends BaseModel { @EruptField( views = @View(title = "文本"), edit = @Edit(title = "文本", notNull = true, search = @Search) ) private String input; @EruptField( views = @View(title = "数值", sortable = true), edit = @Edit(title = "数值", search = @Search) ) private Float number; @EruptField( views = @View(title = "布尔"), edit = @Edit(title = "布尔", search = @Search) ) private Boolean bool; @EruptField( views = @View(title = "时间"), edit = @Edit(title = "时间", search = @Search(vague = true)) ) private Date date; @EruptField( views = @View(title = "滑动条"), edit = @Edit(title = "滑动条", type = EditType.SLIDER, search = @Search, sliderType = @SliderType(max = 90, markPoints = {0, 30, 60, 90}, dots = true)) ) private Integer slide; @EruptField( views = @View(title = "下拉选择"), edit = @Edit( search = @Search, title = "下拉选择", type = EditType.CHOICE, choiceType = @ChoiceType(fetchHandler = SqlChoiceFetchHandler.class, fetchHandlerParams = "select id,name from e_upms_menu" ) ) ) private Long choice; } 特性 自动建表:表结构自动生成,无需手动建表 易于上手:会简单的Spring Boot基础知识即可 使用简单:仅需了解@Erupt与@EruptField两个注解即可上手开发 代码简洁:仅需一个.java文件,template、controller、service、dao 都不需要创建 功能强大:动态条件处理,逻辑删除,LDAP,自定义登录逻辑,RedisSession,操作日志等 多数据源:支持:MySQL、Oracle、SQL Server、PostgreSQL、H2,甚至支持MongoDB 高扩展性:支持自定义数据源实现、自定义登录逻辑、动态权限管理、生命周期函数、自定义 OSS 大量组件:滑动输入、时间选择、一对多、图片上传、代码编辑、自动完成、树、多对多、地图等 23 类组件 丰富展示:普通文本、二维码、链接、图片、HTML、代码段、iframe、swf 等 低侵入性:几乎所有功能都围绕注解而展开,不影响 Spring Boot 其他功能或三方库库的使用 前后端分离:后端与前端可分开部署 响应式布局:支持 PC 端手机端等各种规格的设备中使用 自定义页面:支持自定义页面,自定义弹出层,且支持:原生 H5 / Freemarker / Thymeleaf 等方式渲染 前端零代码:前端布局自动构建,一行前端代码都不用写 无需二次开发:仅需引用 jar 包即可 ! 完全不需要了解Angular / React / Vue / Jquery 而且不需要了解JavaScript / HTML / CSS 甚至不需要了解Spring MVC / Mybatis / SQL 在线体验 演示地址:https://www.erupt.xyz/demo 账号密码:guest / guest 支持主流 4 款现代浏览器,以及 Internet Explorer 11+,可直接运行在 Electron 等基于 Web 标准的环境上 演示截图

优秀的个人博客,低调大师

Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析(6)

接下来,我们再来看看server模块的实现。在external/ashmem/common目录下,只有一个源文件SharedBufferServer.cpp,它实现了内存共享服务SharedBufferService: #defineLOG_TAG"SharedBufferServer" #include<utils/Log.h> #include<binder/MemoryBase.h> #include<binder/MemoryHeapBase.h> #include<binder/IServiceManager.h> #include<binder/IPCThreadState.h> #include"../common/ISharedBuffer.h" classSharedBufferService:publicBnSharedBuffer { public: SharedBufferService() { sp<MemoryHeapBase>heap=newMemoryHeapBase(SHARED_BUFFER_SIZE,0,"SharedBuffer"); if(heap!=NULL) { mMemory=newMemoryBase(heap,0,SHARED_BUFFER_SIZE); int32_t*data=(int32_t*)mMemory->pointer(); if(data!=NULL) { *data=0; } } } virtual~SharedBufferService() { mMemory=NULL; } public: staticvoidinstantiate() { defaultServiceManager()->addService(String16(SHARED_BUFFER_SERVICE),newSharedBufferService()); } virtualsp<IMemory>getBuffer() { returnmMemory; } private: sp<MemoryBase>mMemory; }; intmain(intargc,char**argv) { SharedBufferService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); return0; } SharedBufferService服务实现了BnSharedBuffer接口。在它的构造函数里面,首先是使用MemoryHeapBase类创建了一个匿名共享内存,大小为SHARED_BUFFER_SIZE。接着,又以这个MemoryHeapBase对象为参数,创建一个MemoryBase对象,这个MemoryBase对象指定要维护的匿名共享内存的的偏移位置为0,大小为SHARED_BUFFER_SIZE,并且,将这个匿名共享内存当作一个整型变量地址,将它初始化为0。最终,这个匿名共享内存对象保存在SharedBufferService类的成员变量mMemory中,这个匿名共享内存对象可以通过成员函数getBuffer来获得。 在Server端应用程序的入口函数main中,首先是调用SharedBufferService静态成员函数instantiate函数来创建一个SharedBufferService实例,然后通过defaultServiceManager函数来获得系统中的Service Manager接口,最后通过这个Service Manager接口的addService函数来把这个SharedBufferService服务添加到Service Manager中去,这样,Client端就可以通过Service Manager来获得这个共享内存服务了。有关Service Manager的实现,请参考前面一篇文章 浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路 ,而用来获取Service Manager接口的defaultServiceManager函数的实现可以参考另外一篇文章 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路 。初始化好这个共享内存服务之后,程序就通过ProcessState::self()->startThreadPool()函数来创建一个线程等待Client端来请求服务了,最后,程序的主线程也通过IPCThreadState::self()->joinThreadPool()函数来进入到等待Client端来请求服务的状态中。 我们还需要为这个Server端应用程序编译一个编译脚本,在external/ashmem/server目录下,新建一个Android.mk文件,它的内容如下所示: LOCAL_PATH:=$(callmy-dir) include$(CLEAR_VARS) LOCAL_MODULE_TAGS:=optional LOCAL_SRC_FILES:=../common/ISharedBuffer.cpp\ SharedBufferServer.cpp LOCAL_SHARED_LIBRARIES:=libcutilslibutilslibbinder LOCAL_MODULE:=SharedBufferServer include$(BUILD_EXECUTABLE) 最后,我们再来看看client模块的实现。在external/ashmem/client目录下,只有一个源文件SharedBufferClient.cpp,它的内容如下所示: #defineLOG_TAG"SharedBufferClient" #include<utils/Log.h> #include<binder/MemoryBase.h> #include<binder/IServiceManager.h> #include"../common/ISharedBuffer.h" intmain() { sp<IBinder>binder=defaultServiceManager()->getService(String16(SHARED_BUFFER_SERVICE)); if(binder==NULL) { printf("Failedtogetservice:%s.\n",SHARED_BUFFER_SERVICE); return-1; } sp<ISharedBuffer>service=ISharedBuffer::asInterface(binder); if(service==NULL) { return-2; } sp<IMemory>buffer=service->getBuffer(); if(buffer==NULL) { return-3; } int32_t*data=(int32_t*)buffer->pointer(); if(data==NULL) { return-4; } printf("Thevalueofthesharedbufferis%d.\n",*data); *data=*data+1; printf("Addvalue1tothesharedbuffer.\n"); return0; } 在这个文件中,主要就是定义了Client端应用程序的入口函数main,在这个main函数里面,首先通过Service Manager接口获得前面所实现的匿名共享内存服务SharedBufferService的远程接口service,然后通过这个远程接口的getBuffer成员函数获得由Server端提供的一块匿名共享内存接口buffer,最后通过这个匿名共享内存接口获得这个匿名共享内存的基地址data。有了这个匿名共享内存的地址data之后,我们就可以对它进行读写了,先是把这个匿名共享内存当作是一个整型变量地址进行访问,并输出它的值的大小,然后对这个整量变量进行加1的操作,并写回到原来的共享内存空间中去。这样,当Server端应用程序运行之后,第一次运行这个Client端应用程序时,输出的值为0,第二次运行这个个Client端应用程序时,输出的值为1,第三次运行这个个Client端应用程序时,输出的值为3......依次类推,后面我们将在模拟器中对这个分析进行验证,如果验证成功的话,就说明这个匿名共享内存成功地在Server端和Client端实现共享了。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966923,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析(7)

同样,我们需要为这个Client端应用程序编译一个编译脚本,在external/ashmem/client目录下,新建一个Android.mk文件,它的内容如下所示: LOCAL_PATH:=$(callmy-dir) include$(CLEAR_VARS) LOCAL_MODULE_TAGS:=optional LOCAL_SRC_FILES:=../common/ISharedBuffer.cpp\ SharedBufferClient.cpp LOCAL_SHARED_LIBRARIES:=libcutilslibutilslibbinder LOCAL_MODULE:=SharedBufferClient include$(BUILD_EXECUTABLE) 源代码都准备好了之后,就可以对Server端和Client端应用程序进行编译了。关于如何单独编译Android源代码工程中的模块,以及如何打包system.img,请参考 如何单独编译Android源代码中的模块 一文。 执行以下命令进行编译和打包: USER-NAME@MACHINE-NAME:~/Android$mmmexternal/ashmem/server USER-NAME@MACHINE-NAME:~/Android$mmmexternal/ashmem/client USER-NAME@MACHINE-NAME:~/Android$makesnod 这样,打包好的Android系统镜像文件system.img就包含我们前面创建的Server端应用程序SharedBufferServer和Client端应用程序SharedBufferClient了。 至此,我们就可以运行模拟器来验证我们的程序了。关于如何在Android源代码工程中运行模拟器,请参考 在Ubuntu上下载、编译和安装Android最新源代码 一文。 执行以下命令启动模拟器: USER-NAME@MACHINE-NAME:~/Android$emulator 模拟器运行起来后,就可以通过adb shell命令连上它: USER-NAME@MACHINE-NAME:~/Android$adbshell 最后,进入到/system/bin/目录下: luo@ubuntu-11-04:~/Android$adbshell root@android:/#cdsystem/bin 进入到/system/bin/目录后,首先在后台中运行Server端应用程序SharedBufferServer: root@android:/system/bin#./SharedBufferServer& 然后再在前台中重复运行Client端应用程序SharedBufferClient,以便验证程序的正确性: root@android:/system/bin#./SharedBufferClient Thevalueofthesharedbufferis0. Addvalue1tothesharedbuffer. root@android:/system/bin#./SharedBufferClient Thevalueofthesharedbufferis1. Addvalue1tothesharedbuffer. root@android:/system/bin#./SharedBufferClient Thevalueofthesharedbufferis2. Addvalue1tothesharedbuffer. root@android:/system/bin#./SharedBufferClient Thevalueofthesharedbufferis3. Addvalue1tothesharedbuffer. 如果我们看到这样的输出,就说明我们成功地在Server端应用程序SharedBufferServer和Client端应用程序SharedBufferClietn共享内存中的数据了。 至此,Android系统匿名共享内存的C++调用接口MemoryHeapBase和MemoryBase就分析完成了。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966926,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析(4)

2.MemoryBase 文章开始时说过,MemoryBase接口是建立在MemoryHeapBase接口的基础上的,它们都可以作为一个Binder对象来在进程间进行数据共享,它们的关系如下所示: MemoryBase类包含了一个成员变量mHeap,它的类型的IMemoryHeap,MemoryBase类所代表的匿名共享内存就是通过这个成员变量来实现的。 与MemoryHeapBase的分析过程一样,我们先来看MemoryBase类在Server端的实现,然后再来看它在Client端的实现。 MemoryBase在Server端实现的类图如下所示: MemoryBase类在Server端的实现与MemoryHeapBase类在Server端的实现是类似的,这里只要把IMemory类换成IMemoryHeap类、把BnMemory类换成BnMemoryHeap类以及MemoryBase类换成MemoryHeapBase类就变成是MemoryHeapBase类在Server端的实现了,因此,我们这里只简单分析IMemory类和MemoryBase类的实现。 IMemory类定义了MemoryBase类所需要实现的接口,这个类定义在frameworks/base/include/binder/IMemory.h文件中: classIMemory:publicIInterface { public: ...... virtualsp<IMemoryHeap>getMemory(ssize_t*offset=0,size_t*size=0)const=0; ...... void*pointer()const; size_tsize()const; ssize_toffset()const; }; 成员函数getMemory用来获取内部的MemoryHeapBase对象的IMemoryHeap接口;成员函数pointer()用来获取内部所维护的匿名共享内存的基地址;成员函数size()用来获取内部所维护的匿名共享内存的大小;成员函数offset()用来获取内部所维护的这部分匿名共享内存在整个匿名共享内存中的偏移量。 IMemory类本身实现了pointer、size和offset三个成员函数,因此,它的子类,即MemoryBase类,只需要实现getMemory成员函数就可以了。IMemory类的实现定义在frameworks/base/libs/binder/IMemory.cpp文件中: void*IMemory::pointer()const{ ssize_toffset; sp<IMemoryHeap>heap=getMemory(&offset); void*constbase=heap!=0?heap->base():MAP_FAILED; if(base==MAP_FAILED) return0; returnstatic_cast<char*>(base)+offset; } size_tIMemory::size()const{ size_tsize; getMemory(NULL,&size); returnsize; } ssize_tIMemory::offset()const{ ssize_toffset; getMemory(&offset); returnoffset; } MemoryBase类声明在frameworks/base/include/binder/MemoryBase.h文件中: classMemoryBase:publicBnMemory { public: MemoryBase(constsp<IMemoryHeap>&heap,ssize_toffset,size_tsize); ...... virtualsp<IMemoryHeap>getMemory(ssize_t*offset,size_t*size)const; ...... private: size_tmSize; ssize_tmOffset; sp<IMemoryHeap>mHeap; }; MemoryBase类实现在frameworks/base/libs/binder/MemoryBase.cpp文件中: MemoryBase::MemoryBase(constsp<IMemoryHeap>&heap, ssize_toffset,size_tsize) :mSize(size),mOffset(offset),mHeap(heap) { } sp<IMemoryHeap>MemoryBase::getMemory(ssize_t*offset,size_t*size)const { if(offset)*offset=mOffset; if(size)*size=mSize; returnmHeap; } 在它的构造函数中,接受三个参数,参数heap指向的是一个MemoryHeapBase对象,真正的匿名共享内存就是由它来维护的,参数offset表示这个MemoryBase对象所要维护的这部分匿名共享内存在整个匿名共享内存块中的起始位置,参数size表示这个MemoryBase对象所要维护的这部分匿名共享内存的大小。 成员函数getMemory的实现很简单,只是简单地返回内部的MemoryHeapBase对象的IMemoryHeap接口,如果传进来的参数offset和size不为NULL,还会把其内部维护的这部分匿名共享内存在整个匿名共享内存块中的偏移位置以及这部分匿名共享内存的大小返回给调用者。 这里我们可以看出,MemoryBase在Server端的实现只是简单地封装了MemoryHeapBase的实现。1 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966918,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析(2)

回到前面MemoryHeapBase类的构造函数中,将匿名共享内存映射到本进程的地址空间去后,还看继续设置这块匿名共享内存的读写属性: if(fd>=0){ if(mapfd(fd,size)==NO_ERROR){ if(flags&READ_ONLY){ ashmem_set_prot_region(fd,PROT_READ); } } } 上面调用mapfd函数来映射匿名共享内存时,指定这块内存是可读写的,但是如果传进来的参数flags设置了只读属性,那么还需要调用系统运行时库存层的ashmem_set_prot_region函数来设置这块匿名共享内存为只读,这个函数定义在system/core/libcutils/ashmem-dev.c文件,有兴趣的读者可以自己去研究一下。 这样,通过这个构造函数,一块匿名共享内存就建立好了,其余的三个成员函数getHeapID、getBase和getSize就简单了: intMemoryHeapBase::getHeapID()const{ returnmFD; } void*MemoryHeapBase::getBase()const{ returnmBase; } size_tMemoryHeapBase::getSize()const{ returnmSize; } 接下来我们再来看一下MemoryHeapBase在Client端实现的类图: 这个类图中的类也是可以划分为两部分,一部分是和业务相关的,即跟匿名共享内存操作相关的类,包括BpMemoryHeap、IMemoryBase和RefBase三个类,另一部分是和Binder机制相关的,包括IInterface、BpInterface、BpRefBase、IBinder、BpBinder、ProcessState和IPCThreadState七个类。 在和匿名共享内存操作相关的类中,BpMemoryHeap类是前面分析的MemoryHeapBase类在Client端进程的远接接口类,当Client端进程从Service Manager或者其它途径获得了一个MemoryHeapBase对象的引用之后,就会在本地创建一个BpMemoryHeap对象来代表这个引用。BpMemoryHeap类同样是要实现IMemoryHeap接口,同时,它是从RefBase类继承下来的,因此,它可以与智能指针来结合使用。 在和Binder机制相关的类中,和Server端实现不一样的地方是,Client端不需要实现BnInterface和BBinder两个类,但是需要实现BpInterface、BpRefBase和BpBinder三个类。BpInterface类继承于BpRefBase类,而在BpRefBase类里面,有一个成员变量mRemote,它指向一个BpBinder对象,当BpMemoryHeap类需要向Server端对象发出请求时,它就会通过这个BpBinder对象的transact函数来发出这个请求。这里的BpBinder对象是如何知道要向哪个Server对象发出请深圳市的呢?它里面有一个成员变量mHandle,它表示的是一个Server端Binder对象的引用值,BpBinder对象就是要通过这个引用值来把请求发送到相应的Server端对象去的了,这个引用值与Server端Binder对象的对应关系是在Binder驱动程序内部维护的。这里的ProcessSate类和IPCThreadState类的作用和在Server端的作用是类似的,它们都是负责和底层的Binder驱动程序进行交互,例如,BpBinder对象的transact函数就通过线程中的IPCThreadState对象来将Client端请求发送出去的。这些实现具体可以参考 Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析 一文。 这里我们主要关注BpMemoryHeap类是如何实现IMemoryHeap接口的,这个类声明和定义在frameworks/base/libs/binder/IMemory.cpp文件中: classBpMemoryHeap:publicBpInterface<IMemoryHeap> { public: BpMemoryHeap(constsp<IBinder>&impl); ...... virtualintgetHeapID()const; virtualvoid*getBase()const; virtualsize_tgetSize()const; ...... private: mutablevolatileint32_tmHeapId; mutablevoid*mBase; mutablesize_tmSize; ...... } 先来看构造函数BpMemoryHeap的实现: BpMemoryHeap::BpMemoryHeap(constsp<IBinder>&impl) :BpInterface<IMemoryHeap>(impl), mHeapId(-1),mBase(MAP_FAILED),mSize(0),mFlags(0),mRealHeap(false) { } 它的实现很简单,只是初始化一下各个成员变量,例如,表示匿名共享内存文件描述符的mHeapId值初化为-1、表示匿名内共享内存基地址的mBase值初始化为MAP_FAILED以及表示匿名共享内存大小的mSize初始为为0,它们都表示在Client端进程中,这个匿名共享内存还未准备就绪,要等到第一次使用时才会去创建。这里还需要注意的一点,参数impl指向的是一个BpBinder对象,它里面包含了一个指向Server端Binder对象,即MemoryHeapBase对象的引用。 其余三个成员函数getHeapID、getBase和getSize的实现是类似的: intBpMemoryHeap::getHeapID()const{ assertMapped(); returnmHeapId; } void*BpMemoryHeap::getBase()const{ assertMapped(); returnmBase; } size_tBpMemoryHeap::getSize()const{ assertMapped(); returnmSize; } 即它们在使用之前,都会首先调用assertMapped函数来保证在Client端的匿名共享内存是已经准备就绪了的: voidBpMemoryHeap::assertMapped()const { if(mHeapId==-1){ sp<IBinder>binder(const_cast<BpMemoryHeap*>(this)->asBinder()); sp<BpMemoryHeap>heap(static_cast<BpMemoryHeap*>(find_heap(binder).get())); heap->assertReallyMapped(); if(heap->mBase!=MAP_FAILED){ Mutex::Autolock_l(mLock); if(mHeapId==-1){ mBase=heap->mBase; mSize=heap->mSize; android_atomic_write(dup(heap->mHeapId),&mHeapId); } }else{ //somethingwentwrong free_heap(binder); } } } 在解释这个函数之前,我们需要先了解一下BpMemoryHeap是如何知道自己内部维护的这块匿名共享内存有没有准备就绪的。 在frameworks/base/libs/binder/IMemory.cpp文件中,定义了一个全局变量gHeapCache: staticsp<HeapCache>gHeapCache=newHeapCache(); 它的类型为HeapCache,这也是一个定义在frameworks/base/libs/binder/IMemory.cpp文件的类,它里面维护了本进程中所有的MemoryHeapBase对象的引用。由于在Client端进程中,可能会有多个引用,即多个BpMemoryHeap对象,对应同一个MemoryHeapBase对象(这是由于可以用同一个BpBinder对象来创建多个BpMemoryHeap对象),因此,当第一个BpMemoryHeap对象在本进程中映射好这块匿名共享内存之后,后面的BpMemoryHeap对象就可以直接使用了,不需要再映射一次,当然重新再映射一次没有害处,但是会是多此一举,Google在设计这个类时,可以说是考虑得非常周到的。 我们来看一下HeapCache的实现: classHeapCache:publicIBinder::DeathRecipient { public: HeapCache(); virtual~HeapCache(); ...... sp<IMemoryHeap>find_heap(constsp<IBinder>&binder); voidfree_heap(constsp<IBinder>&binder); sp<IMemoryHeap>get_heap(constsp<IBinder>&binder); ...... private: //ForIMemory.cpp structheap_info_t{ sp<IMemoryHeap>heap; int32_tcount; }; ...... MutexmHeapCacheLock; KeyedVector<wp<IBinder>,heap_info_t>mHeapCache; }; 它里面定义了一个成员变量mHeapCache,用来维护本进程中的所有BpMemoryHeap对象,同时还提供了find_heap和get_heap函数来查找内部所维护的BpMemoryHeap对象的功能。函数find_heap和get_heap的区别是,在find_heap函数中,如果在mHeapCache找不到相应的BpMemoryHeap对象,就会把这个BpMemoryHeap对象加入到mHeapCache中去,而在get_heap函数中,则不会自动把这个BpMemoryHeap对象加入到mHeapCache中去。 这里,我们主要看一下find_heap函数的实现: sp<IMemoryHeap>HeapCache::find_heap(constsp<IBinder>&binder) { Mutex::Autolock_l(mHeapCacheLock); ssize_ti=mHeapCache.indexOfKey(binder); if(i>=0){ heap_info_t&info=mHeapCache.editValueAt(i); LOGD_IF(VERBOSE, "foundbinder=%p,heap=%p,size=%d,fd=%d,count=%d", binder.get(),info.heap.get(), static_cast<BpMemoryHeap*>(info.heap.get())->mSize, static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId, info.count); android_atomic_inc(&info.count); returninfo.heap; }else{ heap_info_tinfo; info.heap=interface_cast<IMemoryHeap>(binder); info.count=1; //LOGD("addingbinder=%p,heap=%p,count=%d", //binder.get(),info.heap.get(),info.count); mHeapCache.add(binder,info); returninfo.heap; } } 这个函数很简单,首先它以传进来的参数binder为关键字,在mHeapCache中查找,看看是否有对应的heap_info对象info存在,如果有的话,就增加它的引用计数info.count值,表示这个BpBinder对象多了一个使用者;如果没有的话,那么就需要创建一个heap_info对象info,并且将它加放到mHeapCache中去了。1 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966900,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

用户登录
用户注册