使用ABAP的RTTI和Java反射机制访问static private属性

In ABAP we can define a static attribute for a class via keyword CLASS-DATA, whose validity is not associated with instances of a class but with the class itself. In order to prove this fact I use the following simple Pointer class for demonstration:

class ZCL_POINT definition
  public
  final
  create public .public section.
  data X type I .
  methods CONSTRUCTOR
    importing
      !IV_X type I
      !IV_Y type I .private section.
  data Y type I .
  class-data COUNT type I .ENDCLASS.CLASS ZCL_POINT IMPLEMENTATION.
  method CONSTRUCTOR.
    me->x = iv_x.
    me->y = iv_y.
    count = count + 1.
  endmethod.ENDCLASS.

In this class, static attribute count is responsible to maintain the number of created Point instances. Then create four point instances:

data(a) = new zcl_point( iv_x = 1 iv_y = 1 ).data(b) = new zcl_point( iv_x = 1 iv_y = 2 ).data(c) = new zcl_point( iv_x = 1 iv_y = 3 ).data(d) = new zcl_point( iv_x = 1 iv_y = 4 ).

Via any variable of a, b, c or d, we can monitor the value of count in debugger.



Can we access the static attribute of a class without object instance in debugger?

Since in theory the static attribute belongs to class instead of any dedicated object instance, so question comes: is there approach to monitor the static attribute value in ABAP debugger directly from class instead? Yes it is possible.

(1) type text “{C:ZCL_POINT} in debugger and press enter key



(2) double click, and you can see the attribute value is directly maintained in class ZCL_POINT, without any object instance created on top of it.



And I try to change its visibility dynamically via class descriptor via the following code and actually it is not possible:

data(lo) = CAST cl_abap_objectdescr( cl_abap_classdescr=>describe_by_name( 'ZCL_POINT' ) ).read TABLE lo->attributes ASSIGNING FIELD-SYMBOL() WITH KEY name = 'COUNT'.CHECK SY-SUBRC = 0.-visibility = 'U'.

Since the structure is read-only and not editable outside cl_abap_objectdescr.



This makes sense otherwise the encapsulation will be violated. Just check many other attribute marked as read-only in Class/Object descriptor class.



Reflection in Java

Check the following code which demonstrates how to access private static attribute value in code via Reflection.

import java.lang.reflect.Field;public class Point {
    private int x;
    private int y;
    static private int count = 0;
    public Point(int x, int y){
        this.x = x;
        this.y = y;
        count++;
    }
    private static void accessStaticPrivate(Point point){
        Class classObject = point.getClass();
        try {
            Field countField = classObject.getDeclaredField("count");
            System.out.println("count: " + countField.get(point));
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException
                | IllegalAccessException e1 ) {
            e1.printStackTrace();
        } 
    }
    public static void main(String[] arg){
        Point a = new Point(1,2);
        accessStaticPrivate(a);
        Point b = new Point(1,3);
        accessStaticPrivate(b);
        Point c = new Point(1,4);
        accessStaticPrivate(c);
        Point d = new Point(1,5);
        accessStaticPrivate(d);
    }}

For ABAPer it is easy to understand the usage of Class object in Java by just comparing it with CL_ABAP_CLASSDESCR in ABAP. When running this small program locally, you will get output in console:

count: 1count: 2count: 3count: 4

Unlike RTTI in ABAP, Java reflection can sometimes lead to  security issues, see one example how Java Singleton would be bypassed in blog  Singleton bypass – ABAP and Java.

要获取更多Jerry的原创文章,请关注公众号"汪子熙":


请使用浏览器的分享功能分享到微信等