Jerry前一篇文章 SAP ABAP一组关键字 IS BOUND, IS NOT INITIAL和IS ASSIGNED的用法辨析 介绍了在ABAP里判断引用变量是否包含了一个有效引用的关键字:IS BOUND.
本文则从ABAP和Java编程语言里不同的引用类型这个角度来继续引用这个话题的讨论。
不知道大家留意过这个ABAP抽象类CL_ABAP_REFERENCE吗?这个抽象类只有一个GET方法,返回一个对象引用。
它的两个子类CL_ABAP_SOFT_REFERENCE和CL_ABAP_WEAK_REFERENCE,分别实现了抽象类的GET方法,不过均在ABAP Kernel里实现的,对ABAP应用开发人员来说,看不见源代码,是一个黑盒子。
怎么使用这个类呢?还是查看SAP帮助文档:
An object in the system class CL_ABAP_WEAK_REFERENCE represents a weak reference to an object in a class. Unlike regular object references, a weak reference is ignored during execution of the garbage collector. This means that a weak reference does not prevent the referenced object from being deleted when the garbage collector is executed.
CL_ABAP_WEAK_REFERENCE类的实例, 代表指向一个对象实例的弱应用。从字面上理解,既然存在弱引用,自然也存在其对立面的强应用。假设有一个ABAP类lcl_person:
DATA: lo_person TYPE REF TO lcl_person.
CREATE OBJECT lo_person.
上述代码定义了一个指向lcl_person对象实例的强引用变量,名为lo_person. 当垃圾回收器工作的时候,只要lcl_person对象实例的强引用lo_person还有效(即没有调用CLEAR, 或者没有被重新赋值指向其他的对象实例), 则lo_person对象实例所占据的内存区域不会被ABAP垃圾回收器释放。换句话说,lcl_person对象实例如果至少存在一个指向它的强引用,则在任何情况下,其内存区域都不会被ABAP垃圾回收器回收。
而弱引用,在垃圾回收阶段会直接被忽略。这就意味着,在ABAP垃圾回收器开始工作的时候,如果一个对象实例并未有任何强引用指向它,此时无论有无弱引用指向它,该对象实例都无法逃脱被回收的命运。
看个具体的例子。
这个30行的ABAP报表,实现了一个简单的LCL_PERSON类。第17行创建了一个该类的实例,该实例的强引用存储在引用变量lo_person里。
第18行创建了一个包裹LCL_PERSON对象实例的弱引用lo_weak. 调用弱引用lo_weak的get方法,在两种不同的情况下有两种不同的返回结果:
(1) 如果第17行创建的lcl_person对象实例已经被垃圾回收器回收了,则get返回一个空引用; (2) 如果lcl_person对象实例没有被回收,则返回指向其的引用。
需要本文源代码的朋友,可以在我的SAP社区博客里找到:
Weak reference in ABAP and Java
我给这个ABAP程序指定了两个输入参数,clear和gc,分别控制是否清除强引用变量lo_person,和是否用代码调用ABAP垃圾回收器。
如果执行程序时传入的参数clear置为true,则调用CLEAR: lo_person. 根据ABAP帮助文档,CLEAR施加在引用变量lo_person上,执行后lo_person指向空引用(null reference).
另一个参数gc置为true,则用代码的方式启动ABAP垃圾回收器:cl_abap_memory_utilities=>do_garbage_collection.
这两个开关的开闭情况,构成了4种不同的排列组合。在这四种排列组合下,由弱引用lo_weak指向的对象实例,是否会被ABAP垃圾回收器回收?结果如下表:
由此可见,弱引用指向的对象实例,在ABAP垃圾回收器启动之后,如果没有再被至少一个强引用变量所指向,则会被垃圾回收器回收。
使用事务码s_memory_inspector,在垃圾回收器启动之后制作一个内存快照(Memory Snapshot),发现在上表第一种排列组合下,lcl_person对象实例已经被回收了: No memory objects found.
而其他三种排列组合下,lcl_person都逃脱了被垃圾回收器回收的命运:
Java里也有对应CL_ABAP_WEAK_REFERENCE的弱引用实现:java.lang.ref.WeakReference.
Jerry本文的ABAP程序,翻译成Java代码如下:
因为这两种编程语言的弱引用,工作原理完全一致,所以上面Java版本的例子Jerry就不赘述了。
上面第25行代码里将强引用变量jerry指向的对象置为null,第26行启动Java垃圾回收器,于是第27行调用弱引用变量get方法得到的结果是:null.
那么这种弱引用有什么使用场景?
最好的学习方式就是对CL_ABAP_WEAK_REFERENCE执行Where-used操作,来查找有哪些SAP标准应用使用到了这个类。
在下图Jerry使用的SAP CRM系统里,弱引用的使用场合还不少。
这500多处使用场景里,最典型的就是缓存(Cache)的实现场景。下图这个CRM增强工具Application Enhancement Tool(简称AET)工厂类的方法GGET_DATA_TYPE_HANDLER, 根据两个输入参数,字段数据类型和字段行为类型,返回对应的处理器实例(handler). 这些处理器实例化时需要从若干张数据库表里读取数据并保存在内存里,因此初始化过程需要花费一定的时间。为了避免这个方法每次被调用时都花费时间重复地访问数据库表,创建新的实例,该工厂类引入了一个缓存机制, 即下图第21行的内表gt_type_handler_cache. 每次GET方法被调用时,先去该内表里查看是否存在对应的处理器实例。如果有,直接返回,省去了费时的处理器实例化工作。
看这个缓存的设计,行项目的类型结构里,handler的类型并不是具体的IF_AXT_DATATYPE_HANDLER, 而是一个弱引用。
技术上说,上图第七行改成:
handler TYPE REF TO IF_AXT_DATATYPE_HANDLER,也是一种正确的设计,而且也正是绝大多数ABAP应用人员最常规的缓存设计方案。为讨论方便,我将这种大家都常用的方案称为方案B,而上图AET工厂类采用弱应用指向处理器实例的方案称为方案A.
方案A的优点是,进可攻退可守。
进可攻,即如果ABAP垃圾回收器没有调用,并且至少存在一个指向某处理器实例的强引用,此时两种方案运行时没有大的差异,唯一的细微区别之处就是方案A在读缓存内表命中,拿到buffer里存放的弱引用之后,再调用弱引用的get方法,拿到处理器实例并返回。而方案B读缓存内表命中后,buffer里存在的就是处理器实例本身,直接返回给调用端即可。
退可守,就是一旦程序里再也没有指向该处理器实例的强引用,并且ABAP垃圾回收器开始工作,那么弱引用指向的处理器实例会被销毁,释放了其消耗的内存。下次如果GET方法再次调用,会从数据库里重新加载数据,初始化处理器实例(下图红色区域), 并重新创建弱引用(下图蓝色区域)。
一言以蔽之,弱引用CL_ABAP_WEAK_REFERENCE最适合用于描述有一定用处,但不是必需驻留在内存里的对象实例。因此在SAP CRM很多框架代码的缓存设计上有着广泛的应用。
其实ABAP除了强引用和弱引用之外,还存在第三种类型的引用:软引用(CL_ABAP_SOFT_REFERENCE).
同弱引用相比,软引用指向的对象,只有当没有被任何强引用指向,且垃圾回收器运行时,系统内存不足时才会被销毁。系统可用内存降低到百分之多少才算是“不足”呢?软引用并未在ABAP里实现,所以我们也无法继续讨论下去。
Java里除了弱引用和软引用之外,还存在PhantomReference(虚引用).
顾名思义,Java里的虚引用就是"形同虚设",因为通过虚引用的get方法,获取到的结果永远为null.
在有的中文资料里,PhantomReference因其这种表现行为,又被翻译成"幻引用","幽灵引用"。这个名字让我想起了《星际争霸》里人族的幽灵战机Wraith.
虚引用主要用来跟踪对象实例被垃圾回收器回收的活动,必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现还有虚引用指向这个对象实例,就会在回收该实例的内存之前,把这个虚引用加入到与之关联的引用队列中。
因为ABAP里根本没有虚引用,所以Jerry也不展开叙述了。
希望本文能让大家对ABAP里两种引用:强引用和弱引用的设计和作用有一个全面了解,同时能知道像Java这种编程语言里,还存在另外两种引用:软引用和虚引用。感谢阅读。
要获取更多Jerry的原创文章,请关注公众号"汪子熙":
相关推荐
【SAP ABAP调用Java生成的Web Service手册】 在SAP系统中,与外部服务进行交互时,经常需要调用由Java等其他语言编写的Web Service。本手册详细介绍了如何在MyEclipse环境中生成Web Service,并在SAP ABAP环境中...
### SAP ABAP与JAVA之间通过RFC传递数据实例详解 #### 需求概述 本文档主要介绍了如何在SAP ABAP系统与JAVA应用程序之间通过RFC(Remote Function Call远程函数调用)实现数据交互的具体实现方法。核心需求是在给定...
详细介绍了SAPABAP开发者必须掌握的包与变更传输系统(CTS)、数据类型、数据库、模块化程序、内表、调试、ABAP数据字典、锁对象、检索帮助、FieldSymbol与数据引用、SAP内存与ABAP内存、报表程序、模块池程序、ABAP...
SAP ABAP(Advanced Business Application Programming)是SAP公司推出的一种高级业务应用编程语言,用于开发在SAP R/3和SAP NetWeaver平台上的应用程序。这些电子书提供了全面的资源,帮助学习者深入理解并掌握SAP ...
SAP是一种全球领先的业务软件系统,它用于企业管理各种复杂流程,包括财务、供应链、人力资源等。...实践是学习编程的最佳途径,这个资源提供了一个良好的起点,帮助你在SAP ABAP的世界里稳步前行。
详细介绍了SAP ABAP开发者必须掌握的包与变更传输系统(CTS)、数据类型、数据库、模块化程序、内表、调试、ABAP数据字典、锁对象、检索帮助、Field Symbol与数据引用、SAP内存与ABAP内存、报表程序、模块池程序、...
在实际项目中,ABAP开发者还需要了解SAP的其他组件,如ABAP对象服务(ABAP Objects)、Web Dynpro(用于创建Web应用程序)和ABAP工作流。此外,还有ABAP测试和调试技巧,以及如何使用ABAP Development Tools(ADT)...
SAP ABAP(Advanced Business Application Programming)是SAP公司开发的一种编程语言,主要用于在其ERP(企业资源规划)系统中创建和定制业务逻辑。在SAP ABAP 1.4.4版本的代码下载中,我们可以深入探讨这个版本的...
SAP ABAP 开发环境和开发工具介绍 SAP ABAP 开发环境和开发工具是 SAP 系统中最重要的组件之一,它提供了一个强大的开发平台,允许开发者创建、测试和部署 ABAP 程序。ABAP 是 SAP 系统中的主要编程语言,用于开发...
《SAP ABAP实用程序开发攻略》这篇文档主要向初学者介绍了SAP ABAP语言以及其在SAP系统开发中的应用,涵盖从基础知识到数据类型和开发工具的详细解释。 首先,文档开篇提到SAP技术架构及发展历程,这为读者提供了一...
《SAP ABAP开发详解与高端应用》这本书深入探讨了SAP ABAP(Advanced Business Application Programming)编程语言,这是SAP系统中用于开发业务应用程序的关键技术。ABAP是SAP平台上的核心编程语言,用于创建自定义...
SAP ABAP 代码备份下载到本地程序代码
SAP ABAP开发学习——第9课:ALV2(视频教程) 1.SAP ABAP开发入门学习 2.含视频教程学习、PPT、作业 3.视频非常清晰
《SAP ABAP开发技术详解(实例篇)(第二版) [1] 》除了对对SAP ABAP开发所需的常用技术(SAP报表、批量导入、对话程序、函数)做了详尽的介绍,包括基本报表、交互式报表、复杂报表、ALV(SAP List Viewer)报表、...
在本课程“SAP ABAP开发学习——第19课:实战讲解”中,我们将深入探讨SAP ABAP(Advanced Business Application Programming)编程语言在实际项目中的应用。ABAP是SAP系统的核心开发语言,用于构建企业级业务应用...
SAP ABAP Query 是 SAP 系统中一种用于创建自定义报表的强大工具,尤其适合那些对 SQL 不太熟悉或者没有数据库直接访问权限的用户。它提供了丰富的功能,使得开发人员可以构建复杂的数据查询,而无需编写大量的 ABAP...
本手册旨在为初级学员提供SAP ABAP的基本知识和实践经验,帮助他们快速掌握ABAP语言的基本语法和开发技术。以下是本手册的知识点概要: 一、ABAP基础语法 * ABAP语言的基本结构和组成 * 变量声明和赋值 * 数据类型...
《SAP ABAP官方教程》是一份针对SAP ABAP编程语言的重要学习资源,适合对这个领域感兴趣的初学者和有经验的开发者。ABAP(Advanced Business Application Programming)是SAP系统中的主要编程语言,用于开发企业级...
针对这种需求,我们可以利用SAP的ABAP编程环境,通过OLE(Object Linking and Embedding)技术来启动Outlook并发送邮件。以下是实现这一功能的关键知识点: 1. **SAP OLE配置**: 在SAP系统中,首先需要进行OLE...