Wednesday 5 July 2017

Weak reference in ABAP and Java

Recently I have some recruitment interview on the topic Weak reference and I think it is necessary for me to refresh my knowledge on this topic.

According to ABAP help, we can wrap an object reference to the so called weak reference, for example see the following code:

lo_person = NEW lcl_person( 'Jerry' ).
lo_weak = NEW cl_abap_weak_reference( lo_person ).


And later we can get the reference to Jerry back via get method provided by weak reference.

lo_person = CAST lcl_person( lo_weak->get( ) ).

The lo_person will become initial only on the conditional that there is no reference pointing to it when Garbage Collector is running. To verify it I wrote the following small program:

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.

There are two switches for this report. The first switch controls whether the reference points to Jerry will be cleared or not, the second one for the fact whether Garbage collection should explicitly be called.


There are four possibilities of combination, and the corresponding result are listed below:

clear reference to Jerry? call Garbage collection? object pointed by weak reference is
cleared by Garbage collector?
Yes Yes Yes 
Yes No No
No Yes No
No No No

In first scenario, in memory snapshot ( tcode s_memory_inspector ) we can clearly see that the object pointed to by lo_person is deleted.


For the left three scenarios, lcl_person instance is not deleted by Garbage collector:


The weak reference in Java behaves the same as ABAP. You can use the following Java code to test it and get the same result:

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;
  WeakReference<Person> person = new WeakReference<Person>(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);
}
}

Soft reference


In my system ( Netweaver 750 SP4 ), the help says soft reference is not implemented.


Since it is not implemented in ABAP, we can test in Java instead.

Use the following Java code to test:

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) {
  SoftReference<Person2> person = new SoftReference<Person2>(new Person2("Jerry"));
  System.out.println(person.get());
  ArrayList<Person2> big = new ArrayList<Person2>();
  for( int i = 0; i < 10000; i++){
   big.add(new Person2(String.valueOf(i)));
  }
  System.gc();
  System.out.println("End: " + person.get());
}
}

This simple program will generate the following output in console:

Hello, I am Jerry
End: Hello, I am Jerry

The reason is, although I have created 10000 Person instance to consume some memory, however the memory consumption is still not so huge enough to make the Jerry person instance wrapped in Soft reference deleted. As a result after System.gc() is called, the reference is still available.

In real Java world , Soft reference is usually used to implemented cache mechanism where limited memory resource is available, for example in Android application development.

1 comment: