Skip to content

Unprotected privates?

by Adrian on July 21st, 2010

I was doing some work on an SDK recently which required that I access a protected member of a class. I didn’t want to have to override the class just to get access to it so I did some digging and discovered some interesting things you can do with Java and the JVM to access not only protected but also private class members.

It made me think a little about how we design classes and assumptions we make about immutability and access to internals. Here I have provided 2 examples of immutable classes. The first is obviosuly not properly immutable simply due to the fact that it’s field is declared protected and not private.

If you need to know what immutability is have a look at Wikipedia

The goal of the exercise is to execute the following code:

Immutable myImmutable =
	new Immutable(new String[]{"Hello", "World"});

//Do some cunning stuff here...

System.out.println(myImmutable );
myImmutable.getValue()[0] = "Goodbye";
System.out.println(myImmutable );

Now both classes are designed to be immutable so that this code should always print:

Hello World
Hello World

But if we put in the right cunning stuff we could get:

Hello World
Goodbye World

Accessing Protected Fields

The “not-so-immutable” class looks like this:

public class Immutable
{
	protected String[] value;

	public Immutable(String[] value)
	{
		this.value = value;
	}

	public String[] getValue()
	{
		//To maintain immutability we copy the array
		String[] return_value = new String[value.length];
		System.arraycopy(
			value, 0,
			return_value, 0,
			value.length);
		return return_value;
	}

	@Override
	public String toString()
	{
		StringBuffer buffer = new StringBuffer();
		for(int i = 0; i < value.length; i++)
		{
			buffer.append(value[i] + " ");
		}
		return buffer.toString();
	}

}

A pretty easy to understand class, but wait till you see how easily we can circumvent the immutability.

Immutable myImmutable =
	new Immutable(new String[]{"Hello", "World"}){
	@Override
	public String[] getValue()
	{
		return value;
	}
};

System.out.println(myImmutable );
myImmutable.getValue()[0] = "Goodbye";
System.out.println(myImmutable );

Accessing Private Fields

Now you might say that the class is not really immutable because you expose the fields to sub-classes. But what if we define exactly the same class but make the field value private.

It’s still possible to expose the field albeit a little more complicated.

Immutable myImmutable =
	new Immutable(new String[]{"Hello", "World"}){
	@Override
	public String[] getValue()
	{
		try
		{
			Class clazz = Immutable.class;
			Field private_field =
				clazz.getDeclaredField("value");
			private_field.setAccessible(true);
			return ((String[]) private_field.get(this));
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}
};

System.out.println(myImmutable );
myImmutable.getValue()[0] = "Goodbye";
System.out.println(myImmutable );

Easy as that.

From → Tech

No comments yet

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS

 

Switch to our mobile site