摘要:當包裹在虛引用實例中的對象引用被垃圾回收器刪除時,虛引用實例本身會自動被插入我之前指定到虛引用構造函數輸入參數的那個隊列中去。
Java編程語言中幾種不同的引用類型是面試時經常容易被問到的問題:強引用,軟引用,弱引用,虛引用。
其實除了Java之外,某些 其他編程語言也有類似概念,比如ABAP。今天我們就來比較一下。
根據ABAP幫助文檔,我們可以把某個對象的引用包在一個Weak Reference的實例里。ABAP的Weak Reference實例通過類CL_ABAP_WEAK_REFERENCE實現。
看下面的例子:首先我在堆上創(chuàng)建了一個新的LCL_PERSON實例,然后包到一個ABAP weak reference里。
lo_person = NEW lcl_person( "Jerry" ).
lo_weak = NEW cl_abap_weak_reference( lo_person ).
稍后,我們想拿到被包裹的lo_person引用時,使用weak reference提供的get方法。見下圖示例:
lo_person = CAST lcl_person( lo_weak->get( ) ).
引用lo_person什么時候會變成initial呢?如果當ABAP垃圾回收器(Garbage Collector)開始工作時,已經沒有任何引用再指向lo_person, 則lo_person會變成initial。
看下面這個例子加深理解。
REPORT ztest. PARAMETERS: clear TYPE char1 as CHECKBOX DEFAULT abap_true, gc TYPE char1 as CHECKBOX DEFAULT abap_true. CLASS lcl_person DEFINITION. PUBLIC SECTION. DATA: mv_name TYPE string. METHODS: constructor IMPORTING !iv_name TYPE string. ENDCLASS. CLASS lcl_person IMPLEMENTATION. METHOD: constructor. me->mv_name = iv_name. ENDMETHOD. ENDCLASS. START-OF-SELECTION. DATA: lo_person TYPE REF TO lcl_person, lo_weak TYPE REF TO cl_abap_weak_reference. lo_person = NEW lcl_person( "Jerry" ). lo_weak = NEW cl_abap_weak_reference( lo_person ). IF clear = abap_true. CLEAR: lo_person. ENDIF. IF gc = abap_true. cl_abap_memory_utilities=>do_garbage_collection( ). ENDIF. lo_person = CAST lcl_person( lo_weak->get( ) ). IF lo_person IS INITIAL. WRITE: / "reference not available". ELSE. WRITE: / "reference still available". ENDIF.
這個report有兩個開關,如下圖。第一個開關控制lo_person這個引用是否被關鍵字CLEAR顯式地置為INITIAL, 第二個開關決定是否在代碼中顯式地調用ABAP垃圾回收器。
這兩個開關的打開和關閉狀態(tài),一共有4種組合。
在第一種情況下,通過關鍵字CLEAR清除了lo_person的引用,從ABAP的內存檢查器(事務碼s_memory_inspector)能發(fā)現,lo_person現在已經不指向任何內存中的對象了。
對于其他三種情況,LCL_PERSON的實例都不會被ABAP垃圾回收器清除:
JavaJava中的weak reference表現行為和ABAP一致。
我把上面的ABAP測試代碼用Java程序重新寫一遍:
import java.lang.ref.WeakReference; class Person { private String mName; public Person(String name) { this.mName = name; } public String getName() { return this.mName; } } public class WeakReferenceTest { public static void check(Person person) { if (person == null) { System.out.println("Reference invalid"); } else { System.out.println("Reference still available"); } } public static void main(String[] args) { Person jerry = null; WeakReferenceABAP Soft reference - ABAP軟應用person = new WeakReference (new Person( "Jerry")); jerry = new Person("Ben"); // if you comment out this line, Reference will be available System.gc(); Person restore = person.get(); check(restore); } }
在我目前使用的ABAP Netweaver 750 SP4系統(tǒng)中,ABAP軟應用尚未實現,
在系統(tǒng)里只有個空的CL_ABAP_SOFT_REFERENCE, 其描述信息寫的是Do Not Use this Class!
那么我們就來試試Java的軟應用 Soft Reference:
package reference; import java.lang.ref.SoftReference; import java.util.ArrayList; class Person2 { private String mName; public Person2(String name) { this.mName = name; } public String getName() { return this.mName; } public void finalize() { System.out.println("finalize called: " + this.mName); } public String toString() { return "Hello, I am " + this.mName; } } public class SoftReferenceTest { public static void main(String[] args) { SoftReferenceperson = new SoftReference (new Person2( "Jerry")); System.out.println(person.get()); ArrayList big = new ArrayList (); for (int i = 0; i < 10000; i++) { big.add(new Person2(String.valueOf(i))); } System.gc(); System.out.println("End: " + person.get()); } }
控制臺打印出的輸出:
Hello, I am Jerry
End: Hello, I am Jerry
即便我創(chuàng)建了1萬個Person對象的實例,確實消耗了一些內存,然后內存消耗還遠遠沒有大到會導致包含在軟應用中的Person2類的引用被JDK刪除掉的程度。因此我在代碼中調用Java的垃圾回收器System.gc()之后,該引用仍然存在。
在Java中,軟應用通常被用來實現在內存資源很有限的環(huán)境下的緩存機制,比如Android手機開發(fā)中。
Java 虛引用 PhantomReference使用下面的代碼測試虛引用:
package aop; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; public class PhantomReferenceTest { public static void main(String[] args) { Object phantomObj; PhantomReference phantomRef, phantomRef2; ReferenceQueue phantomQueue; phantomObj = new String("Phantom Reference"); phantomQueue = new ReferenceQueue(); phantomRef = new PhantomReference(phantomObj, phantomQueue); System.out.println("1 Phantom Reference:" + phantomRef.get()); System.out.println("2 Phantom Queued: " + phantomRef.isEnqueued()); phantomObj = null; System.gc(); System.out.println("3 Anything in Queue? : " + phantomQueue.poll()); if (!phantomRef.isEnqueued()) { System.out.println("4 Requestion finalization."); System.runFinalization(); } System.out.println("5 Anything in Queue?: " + phantomRef.isEnqueued()); phantomRef2 = (PhantomReference) phantomQueue.poll(); System.out.println("6 Original PhantomReference: " + phantomRef); System.out.println("7 PhantomReference from Queue: " + phantomRef2); } }
測試輸出:
1. Phantom Reference: null
2. Phantom Queued: false
3. Anything in Queue? : null
5. Anything in Queue?: true
6. Original PhantomReference: java.lang.ref.PhantomReference@2a139a55
7. PhantomReference from Queue: java.lang.ref.PhantomReference@2a139a55
和之前介紹的弱引用(WeakReference)和軟引用(SoftReference)不同,包裹在虛引用(PhantomReference)中的對象實例無法通過需引用的get方法返回,因此在第一行輸出我們會看到: “1. Phantom Reference: null”.
在上面示例代碼中虛引用PhantomReference的構造函數里, 我傳入了一個隊列作為輸入參數。當包裹在虛引用實例中的對象引用被Java垃圾回收器刪除時,虛引用實例本身會自動被JVM插入我之前指定到虛引用構造函數輸入參數的那個隊列中去。
在System.runFinalization()執(zhí)行之前,phantomRef.isEnqueued()返回false,phantomQueue.poll()返回空。
當phantomObj實例被JVM刪除后, 虛引用PhantomReference本身被加入到隊列中,并且能夠通過隊列提供的API所訪問:phantomQueue.poll(). 打印輸出的第6行和第7行也說明了這一點。
要獲取更多Jerry的原創(chuàng)技術文章,請關注公眾號"汪子熙"或者掃描下面二維碼:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/71749.html
摘要:這是年的第篇文章,也是汪子熙公眾號總共第篇原創(chuàng)文章。使用通過格式發(fā)送和文件到服務器關于格式的詳細說明,參考開發(fā)社區(qū)和的文檔我在前文例子的基礎上稍作修改在里使用兩個類型為的標簽,分別上傳和文件用來測試的本地文件,大小為字節(jié)。 這是 Jerry 2021 年的第 71 篇文章,也是汪子熙公眾號總共第 348 篇原創(chuàng)文章。 Jerry 之前發(fā)布過一篇文章 不使用任何框架,手寫純 Jav...
摘要:方法使用詳細步驟參考我的博客方法使用里的控件詳細步驟參考我的博客方法使用的具體參考我的博客方法利用代碼手動生成的二進制內容具體參考我的博客方法利用里的功能具體步驟參考我的博客參考我博客里的這個例子點擊按鈕后,會調用開源庫,將下圖中的這段高亮 ABAP 方法1:使用ABAP + Adobe Lifecycle Enterprise Service showImg(https://segm...
摘要:方法使用詳細步驟參考我的博客方法使用里的控件詳細步驟參考我的博客方法使用的具體參考我的博客方法利用代碼手動生成的二進制內容具體參考我的博客方法利用里的功能具體步驟參考我的博客參考我博客里的這個例子點擊按鈕后,會調用開源庫,將下圖中的這段高亮 ABAP 方法1:使用ABAP + Adobe Lifecycle Enterprise Service showImg(https://segm...
摘要:方法使用詳細步驟參考我的博客方法使用里的控件詳細步驟參考我的博客方法使用的具體參考我的博客方法利用代碼手動生成的二進制內容具體參考我的博客方法利用里的功能具體步驟參考我的博客參考我博客里的這個例子點擊按鈕后,會調用開源庫,將下圖中的這段高亮 ABAP 方法1:使用ABAP + Adobe Lifecycle Enterprise Service showImg(https://segm...
摘要:本文里提到的所有都是基于版本的,這使得我又一次被鄙視了使用的程序猿鄙視使用的程序猿。因此這些事物碼本身也是可以通過進行增強的。 在Google上根據關鍵字程序員鄙視鏈搜索,會得到68多萬條結果。 showImg(https://segmentfault.com/img/remote/1460000014000687); 玲瑯滿目的搜索結果里是眾多不同維度劃分的鄙視鏈。 其中有一個維度,...
閱讀 2164·2023-04-26 00:00
閱讀 3278·2021-09-24 10:37
閱讀 3539·2021-09-07 09:58
閱讀 1531·2019-08-30 15:56
閱讀 2226·2019-08-30 13:11
閱讀 2321·2019-08-29 16:38
閱讀 970·2019-08-29 12:58
閱讀 1889·2019-08-27 10:54