您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么理解SAP ABAP和Java里的弱引用和軟引用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么理解SAP 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也不展開敘述了。
感謝各位的閱讀,以上就是“怎么理解SAP ABAP和Java里的弱引用和軟引用”的內容了,經過本文的學習后,相信大家對怎么理解SAP ABAP和Java里的弱引用和軟引用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。