Advertisment

Breaching Java Rules with Reflection

author-image
PCQ Bureau
New Update

Have you ever wondered how your favorite IDE manages auto-completion of

method and field names? Even better, how does an object relational (OR) mapping

framework like Hibernate support default fields while persisting entity classes?

If all these questions sound geek, you must give the Reflection API a spin. Much

of the sizzle that has been caused by Java is because of power added by the

Reflection API to change the runtime behavior of an application that's running

inside a Java Virtual Machine (JVM). In this article, we'll look at the runtime

magic that Reflection provides to Hibernate O/R mapping framework and then we'll

use the Java Reflection API to break one of the fundamental rules of the Java

programming language--we'll access a method marked with the private access

modifier from the client code.

Advertisment

Hibernate mapping



To begin with, we'll look at Hibernate OR mapping framework. As an

illustration, consider the following mapping file which declares the persistent

properties of an entity class:

Direct Hit!



Applies To:
Advanced Java SE and Java EE developers



USP: Use Reflection to access a method
marked with private access modifier



Primary Link: http://java.sun.com/docs/
books/tutorial/reflect/index.html



Google Keywords: Java Reflection API


On PCQ Xtreme DVD: \system\Labs\
Reflection



table="PATIENT">

Advertisment

Advertisment

...

Advertisment

How does Hibernate get to know the Java type of the name and address

properties? How does Hibernate instantiate the Patient Plain Old Java Objects (POJO)

entity class? What's the significance of the default-access=field element? All

this and much more are possible through Reflection. Hibernate can access the

fields (including private) directly. Hibernate will try to determine the correct

conversion and mapping type itself without specifying the type attribute in the

mapping. Further, Hibernate recommends that the access of the default 'no

argument' constructor should be at least package level, as Hibernate needs to

instantiate the class through Reflection.

Jargon watch

  •  Hibernate — A framework for

    mapping an object-oriented domain model to a traditional relational

    database. Its purpose is to relieve the developer from a significant

    amount of relational data persistence-related programming tasks.
  •  Plain Old Java Object (POJO)

    — A Java object without any runtime dependencies other than Java Standard

    Edition (SE) classes. The name is used to emphasize that the object in

    question is an ordinary Java object and not a special object.
  •  Reflection — An API that

    enables you to discover
    information

    about fields, methods and constructors of loaded Java classes and even

    modify this information.
Advertisment

Accessing private method using Reflection



According to Java Language Specification (JLS), 'A private class member or

constructor is accessible only within the body of the top level class that

encloses the declaration of the member or constructor.' This is a well known

Java rule that once a method or a field is declared with the private modifier,

it can't be accessed by any other class. But with Reflection, breaking this

fundamental rule is simple. Reflection provides a convenient handle to all

fields and methods irrespective of their accessibility.

We'll design a simple Java stack of patients as a part of our MedTracker

application to provide a LIFO implementation. Apart from the conventional push()

and pop() methods we'll provide an overloaded version of pop() method which

accepts an integer argument. The integral value specifies the number of elements

to be popped from the stack. As an illustration, consider the following code

listing which presents the patient stack:

private Patient<> pop(int elementCount) {

Advertisment

System.out.println("Inside private method

pop(int)");

if (elementCount < 0)

throw new IndexOutOfBoundsException();

Advertisment

Patient newPatients<>=new Patient;

for(int i=0;i="patients;</font">

return newPatients;

}

This code fragment is pretty straight forward. Inside the pop(int

elementCount) method, we've put a simple check for the elementCount argument;

for any negative value passed to this method, we propagate an

IndexOutOfBoundsException (an unchecked exception). For any positive value, we

populate a local array of Patient objects and return the same. Next, we'll call

the private pop(int elementCount) method from a standalone Java client through

Reflection.

Java Reflection API lets you hook on to

private objects and tweak their behavior at run time. The pop() method

appears to remove the given range of items from the stack

Putting Reflection in action



It's time to hit the ground running! We'll write a simple standalone Java

client which will use the reflection API to call the private pop(int

elementCount) method on the stack class. The following code fragment presents

the Stackmain.java class:

package com.pcquest.medtracker.client;

import com.pcquest.medtracker.model.Patient;

import com.pcquest.medtracker.model.Stack;

import java.lang.reflect.*;

public class Stackmain {

public static void main(String<> args)throws

Exception {

Stack s=new Stack(10);

s.push(new Patient("Samuel","Hoffman"));

s.push(new Patient("Richard","Ryan"));

s.push(new Patient("Steve","Beytel"));

System.out.println("The original list is: " +

s);

Class klass = s.getClass();

Class<> paramTypes = { Integer.TYPE };

Method m = klass.getDeclaredMethod("pop",

paramTypes);

Object<> arguments = { new Integer(2) };

m.setAccessible(true);

m.invoke(s, arguments);

System.out.println("The new list is: "

+ s);

}

}

In the Stackmain class we begin by instantiating the stack initially with 10

elements. Next, we get a Class object. The arguments to any method that is

invoked through reflection is passed as an array of Class object. The

getDeclaredMethod returns all methods declared by one class. In the above code

fragment, we get the private pop(int elementCount) method handler. Then we call

the setAccessible() method, passing 'true' to make it available to the caller

program. Finally, the invoke() method invokes the underlying method represented

by the Method object, on the specified object with specified parameters. The

following screenshot depicts the output.

Conclusion



Reflection is a powerful tool in the hands of a developer with which she can

modify the runtime behavior of applications running in the Java virtual machine.

That said; reflection should only be used by experienced developers. According

to the Sun Java Tutorial, “Reflection is powerful, but should not be used

indiscriminately”. Reflection comes at a cost--non-reflective programs are more

responsive. A security manager can prevent reflexive behavior at runtime. As a

thumb rule, Reflection should only be used by experienced developers as

indiscriminate usage could change semantics of a running application and

introduce side effects.

Advertisment