ABAPJava里的弱引用(WeakReference)和軟引用(SoftReference)

      網友投稿 815 2025-04-04

      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垃圾回收器啟動之后,如果沒有再被至少一個強引用變量所指向,則會被垃圾回收器回收。

      ABAP和Java里的弱引用(WeakReference)和軟引用(SoftReference)

      使用事務碼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這種編程語言里,還存在另外兩種引用:軟引用和虛引用。感謝閱讀。

      ABAP Java

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:空頁如何刪除掉(多余空頁如何刪除)
      下一篇:Linux之vmstat命令
      相關文章
      亚洲精品乱码久久久久久不卡| 亚洲AV噜噜一区二区三区| 国产午夜亚洲精品不卡| 亚洲国产精品ⅴa在线观看| 亚洲а∨天堂久久精品9966| 国产.亚洲.欧洲在线| 亚洲国产日韩在线成人蜜芽 | 亚洲另类自拍丝袜第1页| 亚洲精品一区二区三区四区乱码 | 亚洲AV成人无码网站| 日韩国产欧美亚洲v片| 色偷偷噜噜噜亚洲男人| 综合偷自拍亚洲乱中文字幕| 久久亚洲AV成人无码国产电影| 亚洲av乱码中文一区二区三区| 国产精品亚洲综合| 亚洲成aⅴ人片久青草影院| 亚洲精品老司机在线观看| 久久精品亚洲福利| 亚洲色WWW成人永久网址| 久久九九亚洲精品| 亚洲avav天堂av在线不卡| 日韩亚洲Av人人夜夜澡人人爽| 亚洲国产高清美女在线观看| 久久精品国产亚洲AV蜜臀色欲| 亚洲色欲色欲www在线播放| 日韩国产精品亚洲а∨天堂免| 在线观看亚洲免费| 亚洲日韩VA无码中文字幕| 国产亚洲精品久久久久秋霞| 日本红怡院亚洲红怡院最新| 亚洲第一精品在线视频| 亚洲小说区图片区| 亚洲中文字幕无码中文| 国产精品亚洲AV三区| 亚洲日韩中文字幕日韩在线 | 亚洲自偷自偷图片| 久久夜色精品国产亚洲AV动态图 | 亚洲国产人成网站在线电影动漫| 亚洲精品无码久久久久久久 | 亚洲一线产区二线产区区|