Inside Paulo Abrantes' head
[ start | index | login or register ]
start > 2007-09-26 > 1

Java Programming: Proxies and References

Created by pabrantes. Last edited by pabrantes, 302 days ago. Viewed 2,272 times. #5
[diff] [history] [edit] [rdf]
labels

Java Programming: Proxies and References

In the last post - >>Java Programming: References' Package - I presented the different types of references available in Java and possible uses. One of the uses was combining Proxies with SoftReferences. In this post I'll be going through that example in more detail, presenting a possible solution - includes source code - and discussing the advantages and problems of such solution.
I find this idea interesting because it allows to represent an object, whether or not it is actually present in memory and, and gives the possibility of loading and unloading it on demand.

First of all let's define what is a proxy. In wikipedia the following can be read:

A proxy, in its most general form, is a class functioning as an interface to another thing. The other thing could be anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate.
Wikipedia

In other words a proxy is an object that acts as a front end for another object replicating all its behaviour.
Java already contains a >>Proxy object available in the reflection package.

The Proxy object does not contain any public constructors, in order to create an instance the newProxyInstance method has to be invoked. Here's the method's signature:

/** * * @param loader: the classloader that will define the proxy class * @param interfaces: the interfaces the proxy object will be able to replicate * @param invocationHandler: the invocation handler that will handle the proxy */

newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);

Looking at the signature above the first two parameters are clear but what is the third one, what is an InvocationHandler?
InvocationHandler is an interface. When a class implements this interface, invocations will be translated by the JVM to the invocation of a single method called invoke which receives the invoked Method and and array of arguments.

In the following example a simple InvocationHandler is presented, the objective is simple, print the method's name before invoking it.

Example
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy;

public class ProxyTest implements InvocationHandler { private Object proxied;

protected ProxyTest(Object proxied) { this.proxied = proxied; }

public Object getObject() { return proxied; }

public static Object newProxyInstance(Object object) { return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),new ProxyTest(object)); }

public Object invoke(Object proxy, Method method, Object[] arguments) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { System.out.println("Invoking: " + method.getName()); return method.invoke(getObject(),arguments); }

}

With the previous code a simple access control system can be implemented. The invoke method only invoke the method in the object if it's possible to do so. SnipSnap actually does this.

softproxy-uml Now let's apply SoftRerefences to proxies. The concept I'm creating here is simple:
There are persistent objects that can be present in memory or need to be loaded from the database - in this particular example, there's only a >>MockObject. The model can be seen in the picture on the left.
SoftProxy implements ImplementationHandler and contains a SoftReference to an object, which implements IPersistentObject (the proxied object). Since, it's a SoftReference it might be collected, in such case if the object is requested again it will be reloaded into memory.

The possibility of reloading the object into memory on demand can be taken one step further, instead of creating the proxy with the object it should also be possible to create it only with information that allows the object to be loaded when needed. This feature is called >>Lazy Loading.
In this concept code the information needed by the MockObject is very simple and is following:

  1. The object's class
  2. The object's ID
Below there's a flowchart that describes how the invocation of a method - doStuff in this case - is processed. softproxy-flowchart

Advantages and Problems

There are no perfect solutions, so with the flexibility of intercepting the invocations and giving transparency to object loading comes the memory shortage - due to the existence of more object - and less efficiency since class introspection is used. Another drawback in this implementation is that if there's the need to treat each proxy as a distinct implementation of IPersistentObject, multiple interfaces must exist, one for each distinct behaviour. This implies a multiplication of interfaces that in my opinion is bad design.
As any other solution it has to be thought through in order to understand if its what's needed or not.

Worried about the performance I wrote a small test benchmark that measures the time that doStuff - which actually does nothing - takes.

The test is simple, over N iterations invoke doStuff method directly in a PersistentObject and in a SoftProxy (same objects in all iterations). There's also another variable in the test which is the generation of junk objects in order to make the Garbage Collector (GC) collect the SoftReferences.

The test - which is also including in the released source code - contains some metrics. Below two tables are presented with some of the information I've gathered using a PowerPC 1.5Ghz with 512Mb running OS X.

In the following tables delay should be understand as took 1ms or more to complete invocation.

Table 1: No junk generation

Number of iterationsDelay in ProxyProxy Maximum Wait(ms)SoftReference ReloadsDelay in PersistentObjectPersistentObject Maximum Wait(ms) 
1011000 
100322000 
10001022000 
100001622039 
10000065220 269 

Table 2: Junk generation

Number of iterationsDelay in ProxyProxy Maximum Wait(ms)SoftReference ReloadsDelay in PersistentObjectPersistentObject Maximum Wait(ms) 
10222000 
100322000 
10001022011 
100002222059 
100000114221 549 

No measures regarding memory usage are presented because I didn't find out a good way of doing such measures - suggestions are always welcomed - but it's easy to understand that memory usage will increase.
In the worst case scenario there's the SoftProxy object along with a SoftReference and the actual PersistentObject in memory. Although this will only happen when there's no memory shortage because otherwise soft references will collected. In this last cased only the SoftProxy object will be loaded into memory which probably will be smaller than the PersistentObject it represents.

Conclusions

Summing up, I've discussed a way of implementing proxies that can be used for lazy loading, access control, among other possible uses. The SoftReference for the actual object allows the object to be collected in order to free memory. In the drawbacks list we find performance issues and interfaces explosion.

Finally, anyone interested can >>download the source code.

10 comments (by balhau, jpmsi, pabrantes) | post comment
Who am I?
paulo-roca2My name is Paulo Abrantes AKA pabrantes and I'm a software developer. I'm currently employed at >>CIIST working as a Java developer in >>FenixEDU.

This blog is mostly about Java programming, domain driven design and snipsnap bliki developing. Everything written in this blog is my personal opinion and it may not reflect the opinions of my employer and co-workers.


Blog subscription
subscribe by rss subscribe by email

Links
>> Home
>> Paulo's Profile
>> Post History
>> Add to Technorati Favorites
>> Paulo's Photo Gallery
>> WishList
>> Posting without Login

Search Blog
Fellow Bloggers

Recent Posts

Java Programming: Bytecode Injection
Intermission: Sorry For Downtime
Software Developing: Studying The Bliki Domain Model
SnipSnap Developing: Trying to settle a roadmap
System Administration: Load Balancing with Apache
Blogging: Two years have passed
Software Developing: The SnipSnap Saga
Java Programming: Getting your code spicy with Groovy
Software Developing: Fluent Interfaces
Software Developing: Implementing a ShoutBox on SnipsSnip
Software Developing: SnipSnap, SnipIt and SnipSnip
Java Programming: Proxies and Access Control
Java Programming: Proxies and References
Java Programming: References' Package
YALM: Yet Another Layout Modification

For older posts, please refer to post-history for a complete Post History

Logged in Users: (0)
… and 21 Guests.
This is a modified version of snipsnap.org created by >>Paulo Abrantes