Java reflection: Inject data generically and safely I have become interested in reflection and I wrote a class to wrap an Object so that I can access its private instance fields. The code works great. I do not need to wory about the exceptions in the get() and set() methods because I cast the values appropriately through my wrappers accessor/mutators, but I was wondering if there is a better way of dealing with different types?

Example

public class Driver {
    public static void main(String... args) {
        Point p = new Point();

        System.out.printf("Point initialized: %s\n", p);

        PointDecorator mp = new PointDecorator(p);

        mp.setX(2);
        mp.setY(4);

        p = mp.getPoint();

        System.out.printf("Point updated:     %s\n", p);
    }
}


Output

Point initialized: (0, 0)
Point updated:     (2, 4)


As you can see, I have modified the Point Objects fields, although they are inaccessible through traditional method calls. I was able to bypass Java's typechecking which I find both neat and dangerous. Does this mean that anyone can just wrap another persons class, unless it is immutable, and inject data?

Point.java

public class Point {
    private int x, y;

    public Point() {
        this(0, 0);
    }

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public String toString() {
        return String.format("(%d, %d)", x, y);
    }
}


PointDecorator.java

import java.lang.reflect.Field;

public class PointDecorator extends Point {

     protected Point point;

    public PointDecorator(Point point) {
        this.point = point;
    }

    public void setX(int x) {
        set("x", x);
    }

    public int getX() {
        return (Integer) get("x");
    }

    public void setY(int y) {
        set("y", y);
    }

    public int getY() {
        return (Integer) get("y");
    }

    public Point getPoint() {
        return point;
    }

    protected Object get(String fieldName) {
        try {
            return field(fieldName).get(point);
        } catch (Exception e) { }

        return null;
    }

    protected void set(String fieldName, Object value) {
        try {
            field(fieldName).set(point, value);
        } catch (Exception e) { }
    }

    private Field field(String fieldName) {
        try {
            Field f = point.getClass().getDeclaredField(fieldName);
            f.setAccessible(true);
            return f;
        } catch (Exception e) { }

        return null;
    }
}
Essentially you are after the answer to:


  Does this mean that anyone can just wrap another persons class, unless it is immutable, and inject data?


And you are not really interested in a review of your code... right? (By the way, your code looks neat, and covers the bases of your 'academic exercise' quite well).

Java reflection is a dangerous process. On the up-side, reflection is regulated by the Java security system, and it can be enabled or disabled depending on the site, situation, and whatever else people are worried about.

So, if someone has code in your JVM, then they have access to the internals of your program (assuming Java has a permissive setting for it's security - which is the 'default'). On the other hand, other languages (C, cough *cough*) have even more of a problem if someone has been able to 'inject' malicious code in to their program.

It is all about relative-ness. Relative to many languages, Java is quite safe, and it has ways of being even safer.

On the other hand, if you let someone untrusted run code on your JVM then you have bigger problems to worry about.... ;-)

For what it's worth, there are easier ways to produce problematic code, like deserializing 'malicious' instances of values, or simply manipulating the JVM classpath before the program launches.

It's all about perspective....