SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

Jerry前一篇文章 SAP ABAP一组关键字 IS BOUND, IS NOT INITIAL和IS ASSIGNED的用法剖析 介绍了在ABAP里判别引证变量是否包含了一个有用引证的关键字:IS BOUND.

本文则从ABAP和Java编程言语里不同的引证类型这个视点来持续引证这个论题的评论。

不知道咱们留心过这个ABAP抽象类CL_ABAP_REFERENCE吗?这个抽象类只需一个GET办法,回来一个目标引证。

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

它的两个子类CL_ABAP_SOFT_REFERENCE和CL_ABAP_WEAK_REFERENCE,别离完成了抽象类的GET办法,不过均在ABAP Kernel里完成的,对ABAP运用开发人员来说,看不见源代码,是一个黑盒子。

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

怎样运用这个类呢?仍是检查SAP协助文档:

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

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 ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

需求本文源代码的朋友,能够在我的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).

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

另一个参数gc置为true,则用代码的办法发动ABAP废物收回器:cl_abap_memory_utilities=>do_garbage_collection.

这两个开关的开闭状况,构成了4种不同的排列组合。在这四种排列组合下,由弱引证lo_weak指向的目标实例,是否会被ABAP废物收回器收回?成果如下表:

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

由此可见,弱引证指向的目标实例,在ABAP废物收回器发动之后,假如没有再被至少一个强引证变量所指向,则会被废物收回器收回。

运用业务码s_memory_inspector,在废物收回器发动之后制造一个内存快照(Memory Snapshot),发现在上表第一种排列组合下,lcl_person目标实例现已被收回了: No memory objects found.

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

而其他三种排列组合下,lcl_person都逃脱了被废物收回器收回的命运:

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

Java里也有对应CL_ABAP_WEAK_REFERENCE的弱引证完成:java.lang.ref.WeakReference.

Jerry本文的ABAP程序,翻译成Java代码如下:

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

由于这两种编程言语的弱引证,作业原理完全一致,所以上面Java版别的比如Jerry就不赘述了。

上面第25行代码里将强引证变量jerry指向的目标置为null,第26行发动Java废物收回器,所以第27行调用弱引证变量get办法得到的成果是:null.

那么这种弱引证有什么运用场景?

最好的学习办法便是对CL_ABAP_WEAK_REFERENCE履行Where-used操作,来查找有哪些SAP规范运用运用到了这个类。

在下图Jerry运用的SAP CRM体系里,弱引证的运用场合还不少。

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

这500多处运用场景里,最典型的便是缓存(Cache)的完成场景。下图这个CRM增强东西Application Enhancement Tool(简称AET)工厂类的办法GGET_DATA_TYPE_HANDLER, 依据两个输入参数,字段数据类型和字段行为类型,回来对应的处理器实例(handler). 这些处理器实例化时需求从若干张数据库表里读取数据并保存在内存里,因而初始化进程需求花费必定的时刻。为了防止这个办法每次被调用时都花费时刻重复地拜访数据库表,创立新的实例,该工厂类引入了一个缓存机制, 即下图第21行的内表gt_type_handler_cache. 每次GET办法被调用时,先去该内表里检查是否存在对应的处理器实例。假如有,直接回来,省去了费时的处理器实例化作业。

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

看这个缓存的规划,行项目的类型结构里,handler的类型并不是详细的IF_AXT_DATATYPE_HANDLER, 而是一个弱引证。

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

技能上说,上图第七行改成:

handler TYPE REF TO IF_AXT_DATATYPE_HANDLER,也是一种正确的规划,而且也正是绝大多数ABAP运用人员最惯例的缓存规划计划。为评论便利,我将这种咱们都常用的计划称为计划B,而上图AET工厂类选用弱运用指向处理器实例的计划称为计划A.

计划A的长处是,进可攻退可守。

进可攻,即假如ABAP废物收回器没有调用,而且至少存在一个指向某处理器实例的强引证,此刻两种计划运行时没有大的差异,仅有的纤细差异之处便是计划A在读缓存内表射中,拿到buffer里寄存的弱引证之后,再调用弱引证的get办法,拿到处理器实例并回来。而计划B读缓存内表射中后,buffer里存在的便是处理器实例自身,直接回来给调用端即可。

退可守,便是一旦程序里再也没有指向该处理器实例的强引证,而且ABAP废物收回器开端作业,那么弱引证指向的处理器实例会被毁掉,开释了其耗费的内存。下次假如GET办法再次调用,会从数据库里从头加载数据,初始化处理器实例(下图赤色区域), 并从头创立弱引证(下图蓝色区域)。

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

一言以蔽之,弱引证CL_ABAP_WEAK_REFERENCE最适合用于描绘有必定用途,但不是必需驻留在内存里的目标实例。因而在SAP CRM许多结构代码的缓存规划上有着广泛的运用。

其实ABAP除了强引证和弱引证之外,还存在第三种类型的引证:软引证(CL_ABAP_SOFT_REFERENCE).

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

同弱引证比较,软引证指向的目标,只需当没有被任何强引证指向,且废物收回器运行时,体系内存缺乏时才会被毁掉。体系可用内存降低到百分之多少才算是“缺乏”呢?软引证并未在ABAP里完成,所以咱们也无法持续评论下去。

Java里除了弱引证和软引证之外,还存在PhantomReference(虚引证).

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

望文生义,Java里的虚引证便是"形同虚设",由于经过虚引证的get办法,获取到的成果永远为null.

在有的中文材料里,PhantomReference因其这种体现行为,又被翻译成"幻引证","鬼魂引证"。这个姓名让我想起了《星际争霸》里人族的鬼魂战机Wraith.

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

虚引证首要用来盯梢目标实例被废物收回器收回的活动,有必要和引证行列(ReferenceQueue)联合运用。当废物收回器预备收回一个目标时,假如发现还有虚引证指向这个目标实例,就会在收回该实例的内存之前,把这个虚引证加入到与之相关的引证行列中。

SAP ABAP和Java里的弱引证(WeakReference)和软引证(SoftReference)

由于ABAP里底子没有虚引证,所以Jerry也不打开叙说了。

期望本文能让咱们对ABAP里两种引证:强引证和弱引证的规划和效果有一个全面了解,一起能知道像Java这种编程言语里,还存在别的两种引证:软引证和虚引证。感谢阅览。

本文来自云栖社区合作伙伴“汪子熙”,了解相关信息能够重视微信大众号"汪子熙"。