You are on page 1of 14

Java programming dynamics, Part 2: Introducing

reflection
Use run-time class information to limber up your programming
Dennis Sosnoski
President
Sosnoski Software Solutions, Inc.

03 June 2003

Reflection gives your code access to internal information for classes loaded into the JVM and
allows you to write code that works with classes selected during execution, not in the source
code. This makes reflection a great tool for building flexible applications. But watch out -- if
used inappropriately, reflection can be costly. In Part 2 of his series on Java platform internals,
software consultant Dennis Sosnoski provides an introduction to using reflection, as well as
a look at some of the costs involved. You'll also find out how the Java Reflection API lets you
hook into objects at run time.
View more content in this series
In "Java programming dynamics, Part 1," I gave you an introduction to Java programming classes
and class loading. That article described some of the extensive information present in the Java
binary class format. This month I cover the basics of using the Java Reflection API to access and
use some of that same information at run time. To help keep things interesting even for developers
who already know the basics of reflection, I'm including a look at how reflection performance
compares with direct access.

Don't miss the rest of this series


Part 1, "Classes and class loading" (April 2003)
Part 3, "Applied reflection" (July 2003)
Part 4, "Class transformation with Javassist" (September 2003)
Part 5, "Transforming classes on-the-fly" (February 2004)
Part 6, "Aspect-oriented changes with Javassist" (March 2004)
Part 7, "Bytecode engineering with BCEL" (April 2004)
Part 8, "Replacing reflection with code generation" (June 2004)

Using reflection is different from normal Java programming in that it works with metadata -- data
that describes other data. The particular type of metadata accessed by Java language reflection
is the description of classes and objects within the JVM. Reflection gives you run-time access to
Copyright IBM Corporation 2003
Java programming dynamics, Part 2: Introducing reflection

Trademarks
Page 1 of 14

developerWorks

ibm.com/developerWorks/

a variety of class information. It even lets you read and write fields and call methods of a class
selected at run time.
Reflection is a powerful tool. It lets you build flexible code that can be assembled at run time
without requiring source code links between components. But some aspects of reflection can be
problematic. In this article, I'll go into the reasons why you might not want to use reflection in your
programs, as well as the reasons why you would. After you know the trade-offs, you can decide for
yourself when the benefits outweigh the drawbacks.

Beginners' class
The starting point for using reflection is always a java.lang.Class instance. If you want to work
with a predetermined class, the Java language provides an easy shortcut to get the Class instance
directly:
Class clas = MyClass.class;

When you use this technique, all the work involved in loading the class takes place behind the
scenes. If you need to read the class name at run time from some external source, however, this
approach isn't going to work. Instead, you need to use a class loader to find the class information.
Here's one way to do that:
// "name" is the class name to load
Class clas = null;
try {
clas = Class.forName(name);
} catch (ClassNotFoundException ex) {
// handle exception case
}
// use the loaded class

If the class has already been loaded, you'll get back the existing Class information. If the class
hasn't been loaded yet, the class loader will load it now and return the newly constructed class
instance.

Reflections on a class
The Class object gives you all the basic hooks for reflection access to the class metadata. This
metadata includes information about the class itself, such as the package and superclass of
the class, as well as the interfaces implemented by the class. It also includes details of the
constructors, fields, and methods defined by the class. These last items are the ones most often
used in programming, so I'll give some examples of working with them later in this section.

Ask the expert: Dennis Sosnoski on JVM and bytecode


issues
For comments or questions about the material covered in this article series, as well as
anything else that pertains to Java bytecode, the Java binary class format, or general JVM
issues, visit the JVM and Bytecode discussion forum, moderated by Dennis Sosnoski.

Java programming dynamics, Part 2: Introducing reflection

Page 2 of 14

ibm.com/developerWorks/

developerWorks

For each of these three types of class components -- constructors, fields, and methods -- the
java.lang.Class provides four separate reflection calls to access information in different ways.
The calls all follow a standard form. Here's the set used to find constructors:
Constructor getConstructor(Class[] params) -- Gets the public constructor using the
specified parameter types
Constructor[] getConstructors() -- Gets all the public constructors for the class
Constructor getDeclaredConstructor(Class[] params) -- Gets the constructor (regardless
of access level) using the specified parameter types
Constructor[] getDeclaredConstructors() -- Gets all the constructors (regardless of access
level) for the class
Each of these calls returns one or more java.lang.reflect.Constructor instances. This
Constructor class defines a newInstance method that takes an array of objects as its only
argument, then returns a newly constructed instance of the original class. The array of objects are
the parameter values used for the constructor call. As an example of how this works, suppose you
have a TwoString class with a constructor that takes a pair of Strings, as shown in Listing 1:

Listing 1. Class constructed from pair of strings


public class TwoString {
private String m_s1, m_s2;
public TwoString(String s1, String s2) {
m_s1 = s1;
m_s2 = s2;
}
}

The code shown in Listing 2 gets the constructor and uses it to create an instance of the TwoString
class using Strings "a" and "b":

Listing 2. Reflection call to constructor


Class[] types = new Class[] { String.class, String.class };
Constructor cons = TwoString.class.getConstructor(types);
Object[] args = new Object[] { "a", "b" };
TwoString ts = (TwoString)cons.newInstance(args);

The code in Listing 2 ignores several possible types of checked exceptions thrown by the various
reflection methods. The exceptions are detailed in the Javadoc API descriptions, so in the interest
of conciseness, I'm leaving them out of all the code examples.
While I'm on the topic of constructors, the Java programming language also defines a special
shortcut method you can use to create an instance of a class with a no-argument (or default)
constructor. The shortcut is embedded into the Class definition itself like this:
Object newInstance() -- Constructs new instance using default constructor
Even though this approach only lets you use one particular constructor, it makes a very convenient
shortcut if that's the one you want. This technique is especially useful when working with
JavaBeans, which are required to define a public, no-argument constructor.
Java programming dynamics, Part 2: Introducing reflection

Page 3 of 14

developerWorks

ibm.com/developerWorks/

Fields by reflection
The Class reflection calls to access field information are similar to those used to access
constructors, with a field name used in place of an array of parameter types:

Field getField(String name) -- Gets the named public field


Field[] getFields() -- Gets all public fields of the class
Field getDeclaredField(String name) -- Gets the named field declared
Field[] getDeclaredFields() -- Gets all the fields declared by the class

by the class

Despite the similarity to the constructor calls, there's one important difference when it comes to
fields: the first two variants return information for public fields that can be accessed through the
class -- even those inherited from an ancestor class. The last two return information for fields
declared directly by the class -- regardless of the fields' access types.
The java.lang.reflect.Field instances returned by the calls define getXXX and setXXX methods
for all the primitive types, as well as generic get and set methods that work with object references.
It's up to you to use an appropriate method based on the actual field type, though the getXXX
methods will handle widening conversions automatically (such as using the getInt method to
retrieve a byte value).
Listing 3 shows an example of using the field reflection methods, in the form of a method to
increment an int field of an object by name:

Listing 3. Incrementing a field by reflection


public int incrementField(String name, Object obj) throws... {
Field field = obj.getClass().getDeclaredField(name);
int value = field.getInt(obj) + 1;
field.setInt(obj, value);
return value;
}

This method starts to show some of the flexibility possible with reflection. Rather than working
with a specific class, incrementField uses the getClass method of the passed-in object to find the
class information, then finds the named field directly in that class.

Methods by reflection
The Class reflection calls to access method information are very similar to those used for
constructors and fields:
Method getMethod(String name, Class[] params) -- Gets the named public method using
the specified parameter types
Method[] getMethods() -- Gets all public methods of the class
Method getDeclaredMethod(String name, Class[] params) -- Gets the named method
declared by the class using the specified parameter types
Method[] getDeclaredMethods() -- Gets all the methods declared by the class
Java programming dynamics, Part 2: Introducing reflection

Page 4 of 14

ibm.com/developerWorks/

developerWorks

As with the field calls, the first two variants return information for public methods that can be
accessed through the class -- even those inherited from an ancestor class. The last two return
information for methods declared directly by the class, without regard to the access type of the
method.
The java.lang.reflect.Method instances returned by the calls define an invoke method you
can use to call the method on an instance of the defining class. This invoke method takes two
arguments, which supply the class instance and an array of parameter values for the call.
Listing 4 takes the field example a step further, showing an example of method reflection in
action. This method increments an int JavaBean property defined with get and set methods. For
example, if the object defined getCount and setCount methods for an integer count value, you
could pass "count" as the name parameter in a call to this method in order to increment that value.

Listing 4. Incrementing a JavaBean property by reflection


public int incrementProperty(String name, Object obj) {
String prop = Character.toUpperCase(name.charAt(0)) +
name.substring(1);
String mname = "get" + prop;
Class[] types = new Class[] {};
Method method = obj.getClass().getMethod(mname, types);
Object result = method.invoke(obj, new Object[0]);
int value = ((Integer)result).intValue() + 1;
mname = "set" + prop;
types = new Class[] { int.class };
method = obj.getClass().getMethod(mname, types);
method.invoke(obj, new Object[] { new Integer(value) });
return value;
}

To follow the JavaBeans convention, I convert the first letter of the property name to uppercase,
then prepend get to construct the read method name and set to construct the write method name.
JavaBeans read methods just return the value and write methods take the value as the only
parameter, so I specify the parameter types for the methods to match. Finally, the convention
requires the methods to be public, so I use the form of lookup that finds public methods callable on
the class.
This example is the first one where I've passed primitive values using reflection, so let's look at
how this works. The basic principle is simple: whenever you need to pass a primitive value, just
substitute an instance of the corresponding wrapper class (defined in the java.lang package) for
that type of primitive. This applies to both calls and returns. So when I call the get method in my
example, I expect the result to be a java.lang.Integer wrapper for the actual int property value.

Reflecting arrays
Arrays are objects in the Java programming language. Like all objects, they have classes. If you
have an array, you can get the class of that array using the standard getClass method, just as with
any other object. However, getting the class without an existing instance works differently than
for other types of objects. Even after you have an array class there's not much you can do with it
directly -- the constructor access provided by reflection for normal classes doesn't work for arrays,
Java programming dynamics, Part 2: Introducing reflection

Page 5 of 14

developerWorks

ibm.com/developerWorks/

and arrays don't have any accessible fields. Only the base java.lang.Object methods are defined
for array objects.
The special handling of arrays uses a collection of static methods provided by the
java.lang.reflect.Array class. The methods in this class let you create new arrays, get the
length of an array object, and read and write indexed values of an array object.
Listing 5 shows a useful method for effectively resizing an existing array. It uses reflection to create
a new array of the same type, then copies all the data across from the old array before returning
the new array.

Listing 5. Growing an array by reflection


public Object growArray(Object array, int size) {
Class type = array.getClass().getComponentType();
Object grown = Array.newInstance(type, size);
System.arraycopy(array, 0, grown, 0,
Math.min(Array.getLength(array), size));
return grown;
}

Security and reflection


Security can be a complex issue when dealing with reflection. Reflection is often used by
framework-type code, and for this you may want the framework to have full access to your code
without concern for normal access restrictions. Yet uncontrolled access can create major security
risks in other cases, such as when code is executed in an environment shared by untrusted code.
Because of these conflicting needs, the Java programming language defines a multi-level
approach to handling reflection security. The basic mode is to enforce the same restrictions on
reflection as would apply for source code access:
Access from anywhere to public components of the class
No access outside the class itself to private components
Limited access to protected and package (default access) components
There's a simple way around these restrictions, though -- at least sometimes. The Constructor,
Field, and Method classes I've used in the earlier examples all extend a common base class -the java.lang.reflect.AccessibleObject class. This class defines a setAccessible method that
lets you turn the access checks on or off for an instance of one of these classes. The only catch
is that if a security manager is present, it will check that the code turning off access checks has
permission to do so. If there's no permission, the security manager throws an exception.
Listing 6 demonstrates a program that uses reflection on an instance of the Listing 1TwoString
class to show this in action:

Java programming dynamics, Part 2: Introducing reflection

Page 6 of 14

ibm.com/developerWorks/

developerWorks

Listing 6. Reflection security in action


public class ReflectSecurity {
public static void main(String[] args) {
try {
TwoString ts = new TwoString("a", "b");
Field field = clas.getDeclaredField("m_s1");
//
field.setAccessible(true);
System.out.println("Retrieved value is " +
field.get(inst));
} catch (Exception ex) {
ex.printStackTrace(System.out);
}
}
}

If you compile this code and run it directly from the command line without any special parameters,
it'll throw an IllegalAccessException on the field.get(inst) call. If you uncomment the
field.setAccessible(true) line, then recompile and rerun the code, it will succeed. Finally, if
you add the JVM parameter -Djava.security.manager on the command line to enable a security
manager, it will again fail, unless you define permissions for the ReflectSecurity class.

Reflection performance
Reflection is a powerful tool, but suffers from a few drawbacks. One of the main drawbacks is
the effect on performance. Using reflection is basically an interpreted operation, where you tell
the JVM what you want to do and it does it for you. This type of operation is always going to be
slower than just doing the same operation directly. To demonstrate the performance cost of using
reflection, I prepared a set of benchmark programs for this article (see Resources for a link to the
full code).
Listing 7 shows an excerpt from the field access performance test, including the basic test
methods. Each method tests one form of access to fields -- accessSame works with member
fields of the same object, accessOther uses fields of another object accessed directly, and
accessReflection uses fields of another object accessed by reflection. In each case, the methods
perform the same computations -- a simple add/multiply sequence in a loop.

Listing 7. Field access performance test code


public int accessSame(int loops) {
m_value = 0;
for (int index = 0; index < loops; index++) {
m_value = (m_value + ADDITIVE_VALUE) *
MULTIPLIER_VALUE;
}
return m_value;
}
public int accessReference(int loops) {
TimingClass timing = new TimingClass();
for (int index = 0; index < loops; index++) {
timing.m_value = (timing.m_value + ADDITIVE_VALUE) *
MULTIPLIER_VALUE;
}
return timing.m_value;
}
public int accessReflection(int loops) throws Exception {

Java programming dynamics, Part 2: Introducing reflection

Page 7 of 14

developerWorks

ibm.com/developerWorks/

TimingClass timing = new TimingClass();


try {
Field field = TimingClass.class.
getDeclaredField("m_value");
for (int index = 0; index < loops; index++) {
int value = (field.getInt(timing) +
ADDITIVE_VALUE) * MULTIPLIER_VALUE;
field.setInt(timing, value);
}
return timing.m_value;
} catch (Exception ex) {
System.out.println("Error using reflection");
throw ex;
}
}

The test program calls each method repeatedly with a large loop count, averaging the time
measurements over several calls. The time for the first call to each method is not included in the
average, so initialization time isn't a factor in the results. In the test runs for this article, I used a
loop count of 10 million for each call, running on a 1GHz PIIIm system. My timing results with three
different Linux JVMs are shown in Figure 1. All tests used the default settings for each JVM.

Figure 1. Field access times

The logarithmic scale of the chart allows the full range of times to be displayed, but lessens the
visual impact of the differences. In the case of the first two sets of figures (the Sun JVMs), the
execution time using reflection is over 1000 times greater than that using direct access. The IBM
JVM does somewhat better by comparison, but the reflection method still takes more than 700
times as long as the other methods. There were no significant differences in times between the
other two methods on any JVM, though the IBM JVM did run these almost twice as fast as the Sun
JVMs. Most likely, this difference reflects the specialized optimizations used by the Sun Hot Spot
JVMs, which tend to do poorly in simple benchmarks.
Besides the field access time tests, I did the same sort of timing test for method calls. For method
calls, I tried the same three access variations as for field access, with the added variable of using
no-argument methods versus passing and returning a value on the method calls. Listing 8 shows
the code for the three methods used to test the passed-and-returned value form of the calls.

Listing 8. Method access performance test code


public int callDirectArgs(int loops) {
int value = 0;

Java programming dynamics, Part 2: Introducing reflection

Page 8 of 14

ibm.com/developerWorks/

developerWorks

for (int index = 0; index < loops; index++) {


value = step(value);
}
return value;
}
public int callReferenceArgs(int loops) {
TimingClass timing = new TimingClass();
int value = 0;
for (int index = 0; index < loops; index++) {
value = timing.step(value);
}
return value;
}
public int callReflectArgs(int loops) throws Exception {
TimingClass timing = new TimingClass();
try {
Method method = TimingClass.class.getMethod
("step", new Class [] { int.class });
Object[] args = new Object[1];
Object value = new Integer(0);
for (int index = 0; index < loops; index++) {
args[0] = value;
value = method.invoke(timing, args);
}
return ((Integer)value).intValue();
} catch (Exception ex) {
System.out.println("Error using reflection");
throw ex;
}
}

Figure 2 shows my timing results for method calls. Here again, reflection is much slower than
the direct alternative. The differences aren't quite as large as for the field access case, though,
ranging from several hundred times slower on the Sun 1.3.1 JVM to less than 30 times slower
on the IBM JVM for the no-argument case. The test performance for reflection method calls
with arguments are substantially slower than the calls with no arguments on all JVMs. This is
probably partially because of the java.lang.Integer wrapper needed for the int value passed and
returned. Because Integers are immutable, a new one needs to be generated for each method
return, adding considerable overhead.

Java programming dynamics, Part 2: Introducing reflection

Page 9 of 14

developerWorks

ibm.com/developerWorks/

Figure 2. Method call times

Reflection performance was one area of focus for Sun when developing the 1.4 JVM, which shows
in the reflection method call results. The Sun 1.4.1 JVM shows greatly improved performance over
the 1.3.1 version for this type of operation, running about seven times faster in my tests. The IBM
1.4.0 JVM again delivered even better performance for this simple test, though, running two to
three times faster than the Sun 1.4.1 JVM.
I also wrote a similar timing test program for creating objects using reflection. The differences for
this case aren't nearly as significant as for the field and method call cases, though. Constructing
a simple java.lang.Object instance with a newInstance() call takes about 12 times longer
than using new Object() on the Sun 1.3.1 JVM, about four times longer on the IBM 1.4.0
JVM, and only about two times longer on the Sun 1.4.1 JVM. Constructing an array using
Array.newInstance(type, size) takes a maximum of about two times longer than using new
type[size] for any tested JVM, with the difference decreasing as the array size grows.

Reflection summary
Java language reflection provides a very versatile way of dynamically linking program components.
It allows your program to create and manipulate objects of any classes (subject to security
restrictions) without the need to hardcode the target classes ahead of time. These features make
reflection especially useful for creating libraries that work with objects in very general ways. For
example, reflection is often used in frameworks that persist objects to databases, XML, or other
external formats.
Reflection also has a couple of drawbacks. One is the performance issue. Reflection is much
slower than direct code when used for field and method access. To what extent that matters
depends on how reflection is used in a program. If it's used as a relatively infrequent part of
the program's operation, the slow performance won't be a concern. Even the worst-case timing
figures in my tests showed reflection operations taking only a few microseconds. The performance
Java programming dynamics, Part 2: Introducing reflection

Page 10 of 14

ibm.com/developerWorks/

developerWorks

issues only become a serious concern if reflection is used in the core logic of performance-critical
applications.
A more serious drawback for many applications is that using reflection can obscure what's actually
going on inside your code. Programmers expect to see the logic of a program in the source code,
and techniques such as reflection that bypass the source code can create maintenance problems.
Reflection code is also more complex than the corresponding direct code, as can be seen in the
code samples from the performance comparisons. The best ways to deal with these issues are to
use reflection sparingly -- only in the places where it really adds useful flexibility -- and document
its use within the target classes.
In the next installment, I'll give a more detailed example of how to use reflection. This example
provides an API for processing command line arguments to a Java application, a tool you may
find useful for your own applications. It also builds on the strengths of reflection while avoiding the
weaknesses. Can reflection simplify your command line processing? Find out in Part 3 of Java
programming dynamics.

Java programming dynamics, Part 2: Introducing reflection

Page 11 of 14

developerWorks

ibm.com/developerWorks/

Downloads
Description

Name

Size

j-dyn0603.zip

12KB

Java programming dynamics, Part 2: Introducing reflection

Page 12 of 14

ibm.com/developerWorks/

developerWorks

Resources
Extensive use of reflection can have harmful effects on framework performance. For a graphic
example and some related discussions, see the author's XML data binding articles "Data
binding, Part 2: Performance" (developerWorks, January 2003) and "Data binding, Part 3:
JiBX architecture" (developerWorks, April 2003).
For an in-depth tutorial on using reflection, try The Reflection API trail in the Java Tutorial from
Sun.
Find hundreds more Java technology resources on the developerWorks Java technology
zone.

Java programming dynamics, Part 2: Introducing reflection

Page 13 of 14

developerWorks

ibm.com/developerWorks/

About the author


Dennis Sosnoski
Dennis Sosnoski is the founder and lead consultant of Seattle-area Java consulting
company Sosnoski Software Solutions, Inc., specialists in J2EE, XML, and Web
services support. His professional software development experience spans over 30
years, with the last several years focused on server-side Java technologies. Dennis
is a frequent speaker on XML and Java technologies at conferences nationwide, and
chairs the Seattle Java-XML SIG. Contact Dennis at dms@sosnoski.com.
Copyright IBM Corporation 2003
(www.ibm.com/legal/copytrade.shtml)
Trademarks
(www.ibm.com/developerworks/ibm/trademarks/)

Java programming dynamics, Part 2: Introducing reflection

Page 14 of 14

You might also like