JavaBlog.fr / Java.lu DEVELOPMENT,Java,Tools Java: Reflection, javap

Java: Reflection, javap

Hello,

In this article, I want present you the concept of reflection, especially in JAVA world.

First, what is Reflection?
In computer programming, reflection is the ability of a program to review and possibly modify, the internal structures of high-level (eg objects) at runtime.

In OO programming, the reflection allows the introspection of classes i.e. loading a class, creation of an instance and access to the members (static or not), for example the methods’ calls, reading and writing of attributes without knowing the class in advance. Java has an API for reflection which is used mainly to manage extensions/plugins in an application.

I invite you to read the Wikipedia definition http://en.wikipedia.org/wiki/Reflection_(computer_programming).

Use of Reflection
While at first glance, the reflection appears to be reserved for a top-flight programming, but what are the cases of application of reflection?
Following, some concret use cases of reflection:

  • Use reflection to discovery of attributs of a object, to initialize its member variables or instanciate an object from its “definition” at runtime. For example, Spring framework whose the success demonstrates the viability of reflection in this use case.
  • Use reflection to write a generic code generator for a set of classes (like JAXB-XJC).
  • Automatically process the content objects. For example, to display all informations of an object in a page automatically (ie without access to all fields of the object), the use of reflection can be very handy and save a lot time. Indeed, by browsing the contents of an object by reflection, in a nutshell, any structural modification of the object (such as adding a field in the object) is automatically passed effortlessly to all points using this object.
  • The JVM uses reflection to introspect a class of a external library and in error cases, returns with precision a error message allowing its location in code source. For example, a missing method:
    1Java.lang.NoSuchMethodError
    2    At MyOwnClass.main(MyOwnClass.java:123)
  • The dynamic programming of reflection allows to ignore the content of classes and write generic code that can handle any class. This type of programming is typically used by IDEs in the aid in programming or code completion without building of a bank of informations concerning the definition of used services.
  • Reflection is used in the serialization process in the calls and exchanges on networks.
  • …in the development of logging tools, in the SQL script generation for the persistence of an object…etc.

Javap Utility
There are some utilities to make the information available: convert the compiled code (byte code in Java) to a understood language by a human. One such tool is javap, which is available in the SDK and consists of a basic decompiler. In Windows the tools is named Javap.exe, which is present in the directory jdk\bin and its basic syntax is:

1javap com.ho.test.my.own.package.MyOwnClass

For example, below, the description of java.lang.String:

01C:\Program Files (x86)\Java\jdk1.6.0_26\bin>javap java.lang.String
02Compiled from "String.java"
03public final class java.lang.String extends java.lang.Object implements java.io.
04Serializable,java.lang.Comparable,java.lang.CharSequence{
05    public static final java.util.Comparator CASE_INSENSITIVE_ORDER;
06    public java.lang.String();
07    public java.lang.String(java.lang.String);
08    public java.lang.String(char[]);
09    public java.lang.String(char[], int, int);
10    [...]
11    public static java.lang.String valueOf(char[], int, int);
12    public static java.lang.String copyValueOf(char[], int, int);
13    public static java.lang.String copyValueOf(char[]);
14    public static java.lang.String valueOf(boolean);
15    public static java.lang.String valueOf(char);
16    public static java.lang.String valueOf(int);
17    public static java.lang.String valueOf(long);
18    public static java.lang.String valueOf(float);
19    public static java.lang.String valueOf(double);
20    public native java.lang.String intern();
21    public int compareTo(java.lang.Object);
22    static {};
23}

For help:

1javap -help

Implementation of reflection in JAVA
The java.lang.reflect package is devoted to reflection. But the classes java.lang.Class and java.lang.Package are used a lot in the reflection programming. After the compiling of a Java source code, the byte code created contains the meta data including the parent class, implemented interface, constructors, fields, methods,… of compiled code. The characteristics of the object are represented formally by the following main classes:

Java Class Description
Class A class
Package A Package
Method A method of class
Constructor A constructor of class
Field A field/variable of class

This list is not exhaustive because the purpose of this article is to give a first approach of reflection. You could find expressly, some examples of reflection API use (where the ‘o’ variable is ‘Object’):

  • get the classname of an Object,
    1Class c = o.getClass();
    2String name = c.getName();
  • get the Field Object corresponding to a specific public field,
    1Class c = o.getClass();
    2Field f = c.getField(name);
  • get the public fields of an Object,
    1Class c = o.getClass();
    2Field[] ftab = c.getFields();
  • get a method Object corresponding to a specific public method with the defined parameters by the parameterTypes tables
    1Class c = o.getClass();
    2Method m = c.getMethod(name, parameterTypes);
  • get the public methods of an Object
    1Class c = o.getClass();
    2Method[] mtab = c.getMethods();
  • get a Constructor object corresponding to a specific public constructor with the defined parameters by the parameterTypes table
    1Class c = o.getClass();
    2Constructor cons = c.getConstructor(parameterTypes);
  • get the public Constructors of an Object
    1Class c = o.getClass();
    2Constructor[] constab = c.getConstructors();
  • get the implemented interfaces of an Object
    1Class c = o.getClass();
    2Class[] itab = c.getInterfaces();
  • get the super classes of an Object
    1Class c = o.getClass();
    2Class superclass = c.getSuperclass();
  • get the Package object corresponding of an Object
    1Class c = o.getClass();
    2Package pck = c.getPackage();
  • change the value of a public field
    1Class c = o.getClass();
    2Field f = c.getField(name);
    3f.set(o,val);
  • return a public field
    1Class c = o.getClass();
    2Field f = c.getField(name);
    3f.get(o);
  • Invoke a public method
    1Class c = o.getClass();
    2Method m = c.getMethod(name, parameterTypes);
    3m.invoke(o,args);

Reflection and Encapsulation: private, protected, package scopes
So, the methods “getField”, “getFields”, “getMethod” and “getMethods” allow the retrieve the publics fields and methods. However, there are others methods named “getDeclaredFields” and “getDeclaredMethods” which give the possibilities to violate the rules of encapsulation, in being able to see the characteristics of private, protected fields and methods. The Reflection API allows thus, the virtual machine to be able to explore all elements of a class, but especially the necessity to dispose of all meta data in order to detect errors in running.

  • get a specific Field object corresponding to public, private or protected field,
    1Class c = o.getClass();
    2Field f = c.getDeclaredField(name);
    3f.setAccessible(true);
  • get the Public, private and protected fields of an Object,
    1Class c = o.getClass();
    2Field[] ftab = c.getDeclaredFields();
    3for (int i = 0; i < ftab.length; i++) {
    4    ftab[i].setAccessible(true);
    5}
  • get a Method object corresponding to a specific public, private or protected method with the defined parameters by the parameterTypes table,
    1Class c = o.getClass();
    2Method m = c.getDeclaredMethod(name, parameterTypes);
    3m.setAccessible(true);
  • get the Public, private or protected methods of an Object,
    1Class c = o.getClass();
    2Method[] mtab = c.getDeclaredMethods();
    3for (int i = 0; i < mtab.length; i++) {
    4    mtab[i].setAccessible(true);
    5}
  • get a Constructor object corresponding to public, private or protected constructor with the defined parameters by the parameterTypes table,
    1Class c = o.getClass();
    2Constructor cons = c.getDeclaredConstructor(parameterTypes);
    3cons.setAccessible(true);
  • get the Public, private or protected constructors of an Object,
    1Class c = o.getClass();
    2Constructor[] constab = c.getDeclaredConstructors();
    3for (int i = 0; i < constab.length; i++) {
    4    constab[i].setAccessible(true);
    5}
  • modify a public, private or protected field,
    1Field f = this.getDeclaredField(o, name);
    2f.setAccessible(true);
    3f.set(o,val);
  • return a specific public, private or protected field,
    1Field f = this.getDeclaredField(o, name);
    2f.setAccessible(true);
    3f.get(o);
  • invoke a specific public, private or protected method,
    1Class[] paramTypes = null;
    2paramTypes = new Class[args.length];
    3for(int i=0;i<args.length;++i){
    4    paramTypes[i] = args[i].getClass();
    5}
    6Method m = this.getDeclaredMethod(o, name, paramTypes);
    7m.setAccessible(true);
    8m.invoke(o,args);

By calling the setAcessible(true) method on Field or Method objects, the access checks are turned off for the particular Field or Method instance, for reflection only.
So, the access of private, protected or package scoped fields or methods are possible, and even, its value can be modified.

Reflection Tools Class
In order to benefit of above reflection concepts, I propose a tools class:

001package com.ho.test.reflexion;
002 
003import java.lang.reflect.Constructor;
004import java.lang.reflect.Field;
005import java.lang.reflect.Method;
006 
007/**
008 * Reflection Tools Class
009 * @author Huseyin OZVEREN
010 *
011 */
012public class ReflectionTools {
013    public ReflectionTools() { }
014 
015    // Classname
016    public String getName(Object o) throws Exception {
017        Class c = o.getClass();
018        String name = c.getName();
019        System.out.println("getName=" + name);
020        return name;
021    }
022 
023    // Field Object corresponding to a specific public field
024    public Field getField(Object o, String name) throws Exception {
025        Class c = o.getClass();
026        Field f = c.getField(name);
027        System.out.println("getField=" + f.toString());
028        return f;
029    }
030 
031    // Public fields of an Object
032    public Field[] getFields(Object o) throws Exception {
033        Class c = o.getClass();
034        Field[] ftab = c.getFields();
035        for (int i = 0; i < ftab.length; i++) {
036            System.out.println("getFields ftab[" + i + "]=" + ftab[i].toString());
037        }
038        return ftab;
039    }
040 
041    // Method Object corresponding to a specific public method with the defined parameters by the parameterTypes tables
042    public Method getMethod(Object o, String name, Class... parameterTypes)throws Exception {
043        Class c = o.getClass();
044        Method m = c.getMethod(name, parameterTypes);
045        System.out.println("getMethod=" + m.toString());
046        return m;
047    }
048 
049    // Public methods of an Object
050    public Method[] getMethods(Object o) throws Exception {
051        Class c = o.getClass();
052        Method[] mtab = c.getMethods();
053        for (int i = 0; i < mtab.length; i++) {
054            System.out.println("getMethods mtab[" + i + "]=" + mtab[i].toString());
055        }
056        return mtab;
057    }
058 
059    // Constructor object corresponding to a specific public constructor with the defined parameters by the parameterTypes table
060    public Constructor getConstructor(Object o, Class... parameterTypes) throws Exception {
061        Class c = o.getClass();
062        Constructor cons = c.getConstructor(parameterTypes);
063        System.out.println("getConstructor=" + cons.toString());
064        return cons;
065    }
066 
067    // Public Constructors of an Object
068    public Constructor[] getConstructors(Object o) throws Exception {
069        Class c = o.getClass();
070        Constructor[] constab = c.getConstructors();
071        for (int i = 0; i < constab.length; i++) {
072            System.out.println("getConstructors constab[" + i + "]=" + constab[i].toString());
073        }
074        return constab;
075    }
076 
077    // Implemented interfaces of an Object
078    public Class[] getInterfaces(Object o) throws Exception {
079        Class c = o.getClass();
080        Class[] itab = c.getInterfaces();
081        for (int i = 0; i < itab.length; i++) {
082            System.out.println("getInterfaces itab[" + i + "]=" + itab[i].toString());
083        }
084        return itab;
085    }
086 
087    // Super classes of an Object
088    public Class getSuperclass(Object o) throws Exception {
089        Class c = o.getClass();
090        Class superclass = c.getSuperclass();
091        System.out.println("getSuperclass=" + superclass.toString());
092        return superclass;
093    }
094 
095    // Package object corresponding of an Object
096    public Package getPackage(Object o) throws Exception {
097        Class c = o.getClass();
098        Package pck = c.getPackage();
099        System.out.println("getPackage=" + pck.toString());
100        return pck;
101    }
102 
103    // Change the value of a public field
104    public void changeFieldValue(Object o, String name, Object val) throws Exception {
105        Field f = this.getField(o, name);
106        f.set(o,val);
107    }
108     
109    // Return a public field
110    public Object getFieldValue(Object o, String name) throws Exception {
111        Field f = this.getField(o, name);
112        return f.get(o);
113    }
114 
115    // Invoke a public method
116    public Object invokeMethod(Object o, String name, Object[] args) throws Exception {
117      Class[] paramTypes = null;
118      if(args != null)
119      {
120        paramTypes = new Class[args.length];
121        for(int i=0;i<args.length;++i){
122          paramTypes[i] = args[i].getClass();
123        }
124      }
125      Method m = this.getMethod(o, name, paramTypes);
126      return m.invoke(o,args);
127    }
128     
129    //##############################################
130    // Important Note: unlike "getFields" and "getMethods" methods, the methods "getDeclaredFields" and "getDeclaredMethods"
131    // do not return the information inherited. In this case, it is necessary to go ask the parent class.
132    //##############################################
133 
134    // Get a specific Field object corresponding to public, private or protected field
135    public Field getDeclaredField(Object o, String name) throws Exception {
136        Class c = o.getClass();
137        Field f = c.getDeclaredField(name);
138        f.setAccessible(true);
139        System.out.println("getDeclaredField=" + f.toString());
140        return f;
141    }
142 
143    // Public, private and protected fields of an Object
144    public Field[] getDeclaredFields(Object o) throws Exception {
145        Class c = o.getClass();
146        Field[] ftab = c.getDeclaredFields();
147        for (int i = 0; i < ftab.length; i++) {
148            ftab[i].setAccessible(true);
149            System.out.println("getDeclaredFields ftab[" + i + "]=" + ftab[i].toString());
150        }
151        return ftab;
152    }
153 
154    // Method object corresponding to a specific public, private or protected method with the defined parameters by the parameterTypes table
155    public Method getDeclaredMethod(Object o, String name, Class... parameterTypes)throws Exception {
156        Class c = o.getClass();
157        Method m = c.getDeclaredMethod(name, parameterTypes);
158        m.setAccessible(true);
159        System.out.println("getDeclaredMethod=" + m.toString());
160        return m;
161    }
162 
163    // Public, private or protected methods of an Object
164    public Method[] getDeclaredMethods(Object o) throws Exception {
165        Class c = o.getClass();
166        Method[] mtab = c.getDeclaredMethods();
167        for (int i = 0; i < mtab.length; i++) {
168            mtab[i].setAccessible(true);
169            System.out.println("getDeclaredMethods mtab[" + i + "]=" + mtab[i].toString());
170        }
171        return mtab;
172    }
173 
174    // Constructor object corresponding to public, private or protected constructor
175    // with the defined parameters by the parameterTypes table
176    public Constructor getDeclaredConstructor(Object o, Class... parameterTypes) throws Exception {
177        Class c = o.getClass();
178        Constructor cons = c.getDeclaredConstructor(parameterTypes);
179        cons.setAccessible(true);
180        System.out.println("getDeclaredConstructor=" + cons.toString());
181        return cons;
182    }
183 
184    // Public, private or protected constructors of an Object
185    public Constructor[] getDeclaredConstructors(Object o) throws Exception {
186        Class c = o.getClass();
187        Constructor[] constab = c.getDeclaredConstructors();
188        for (int i = 0; i < constab.length; i++) {
189            constab[i].setAccessible(true);
190            System.out.println("getDeclaredConstructors constab[" + i + "]=" + constab[i].toString());
191        }
192        return constab;
193    }  
194     
195    // Modify a public, private or protected field
196    public void changeDeclaredFieldValue(Object o, String name, Object val) throws Exception {
197        Field f = this.getDeclaredField(o, name);
198        f.setAccessible(true);
199        f.set(o,val);
200    }
201     
202    // Return a specific public, private or  protected field
203    public Object getDeclaredFieldValue(Object o, String name) throws Exception {
204        Field f = this.getDeclaredField(o, name);
205        f.setAccessible(true);
206        return f.get(o);
207    }
208 
209    // Invoke a specific public, private or protected method
210    public Object invokeDeclaredMethod(Object o, String name, Object[] args) throws Exception {
211      Class[] paramTypes = null;
212      if(args != null)
213      {
214        paramTypes = new Class[args.length];
215        for(int i=0;i<args.length;++i){
216          paramTypes[i] = args[i].getClass();
217        }
218      }
219      Method m = this.getDeclaredMethod(o, name, paramTypes);
220      m.setAccessible(true);
221      return m.invoke(o,args);
222    }  
223}

Download
The attachment java_reflexion.zip contains a project with:
+ TestClassInstance extends SuperTestClassInstance implements Serializable, ITestClassInstance: Class to check via reflection,
+ ITestClassInstance: Interface of class to check via reflection,
+ SuperTestClassInstance: Super class of class to check via reflection,
+ ReflectionTools: ReflectionTools,
+ JUClassToolsWithTestClassInstance: JUNIT testcase to test the reflection,

java_reflexion.zip

Best regards,

Huseyin OZVEREN

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.

Related Post

Thank you…Thank you…

I would thank the visitors of my blog. Currently, this blog has over more 300 unique visitors by day without advertising. I know that I didn’t post new article from