Showing posts with label Java Reflection. Show all posts
Showing posts with label Java Reflection. Show all posts

Sunday, 11 December 2022

More on Dynamic proxy

This is a follow up post from dynamic proxy to share about more realistic examples of dynamic proxy.

Today's software development is heavily reliant on system observability. Observability helps us to understand when the system degrades or misbehaves so that we can take proactive measures to fix it. 

  
Toy service for this example will be FXService 

public interface FXService {

double convert(String from, String to, int amount);
}

This service will use https://api.exchangerate.host API for FX conversion.




Lets look at what types of dynamic proxy we can create on top of this.

Method Timing

It will keep track of method execution time and make it available later for analysis or other purposes. Using this proxy, X slow-running methods will be provided.
In FXService, there is only one method, so this proxy will create a method key with the method name and parameters.


Method timing proxy will show top X slow running method for eg. 


Method convert( SGD,IDR,1 ) took 1041 ms
Method convert( SGD,GBP,1 ) took 994 ms
Method convert( SGD,USD,1 ) took 983 ms
Method convert( SGD,IDR,1 ) took 672 ms
Method convert( SGD,INR,1 ) took 650 ms
Method convert( SGD,USD,1 ) took 593 ms
Method convert( SGD,JPY,1 ) took 593 ms
Method convert( SGD,GBP,1 ) took 582 ms
Method convert( SGD,USD,1 ) took 580 ms
Method convert( SGD,INR,1 ) took 566 ms

Such type of proxy is very helpful in identifying outage or degradation in API.

Stand In Processing

Proxy services such as this can be used to provide stand-in processing when the underlying service is down. For example, when a real FX service is down, this proxy can answer queries from the last successful call.




It is useful for not only enhancing availability but also improving latency, since such a service can answer queries from the local cache right away. Additionally, it may be possible to save some costs if the underlying API is charged by usage.


Chain of proxy

Nice thing about proxies is that multiple proxies can be composed together to create a complex chain of proxy. For example, we can chain Stand In & Method timing together to get features of both.



Below code snippet is creating chain of proxy

FXService core = new FXServiceAPI("https://api.exchangerate.host", 1);
FXService timeRecorderProxy = create(FXService.class, new TimeRecorderProxy(core, tracker));
FXService standInProxy = create(FXService.class, new StandInProcessingProxy(timeRecorderProxy, cache));
FXService fx = standInProxy; 


Full code using all the proxy

List<String> currency = new ArrayList<String>() {{
add("USD");
add("INR");
add("GBP");
add("IDR");
add("JPY");
add("CAD");
}};

IntStream.range(0, 100).forEach($ -> {
Collections.shuffle(currency);
currency.parallelStream().forEach(code -> {
try {
Double d = fx.convert("SGD", code, 1);
System.out.println(d);
} catch (Exception e) {
System.out.println("Failed for " + code);
}
});
});

tracker.dumpSlowRequests(10);
cache.prettyPrint();



Code used in this post is available @ fx service

Conculsion

A dynamic proxy is a powerful tool that is part of Java's ecosystem. It can be a very useful tool for writers of libraries or frameworks, since a proxy's primary purpose is to extend the functionality of an underlying service/api. Therefore, special precautions must be taken to ensure that it does not negatively impact the underlying service.


 

Saturday, 7 November 2020

Private method or state testing in JVM

Unit testing private method is not recommended but some time we are in situation when unit test requires to inspect private state of object. As guideline we must avoid such type of design but some time especially when using some framework or library we are left with no options.




One of the such thing i found recently while writing some unit test around spark data frame. As part of one of the feature dataframe/dataset caching was required and no easy way to verify whether caching was done or not. I didn't want to add other layer of abstraction on Spark API to do this.

Code snippet that needs to be tested. 

sparkSession.read
.parquet("....")
.cache // Cache this DF/DS
.createOrReplaceGlobalTempView("mysupertable")

Java has excellent support for Metaprogramming from day 1 and reflection plays big role it that. Reflection can be used in such scenario.

sparkSession.sharedState.cacheManager maintain cached tables details. 

CacheManager is internal spark class and may change with new spark version , so test based on internal details has risk of breaking but it also gives good idea about internals of framework.

Lets try to access private state of cachemanager via java reflection.

Below code snippet will search the fields with specific pattern and make it accessible. 

def fieldValue[T](fieldName: String, obj: Any, cls: Class[T]): T = {
val field = {
val matchedField = classOf[CacheManager].getDeclaredFields()
.filter(_.getName().endsWith(fieldName))
.map(f => {
f.setAccessible(true)
f
})
.head
matchedField
}

field
.get(obj)
.asInstanceOf[T]
}

setAccessible(true) is the key thing, it is required for private or protected members.
One more to highlight that "endsWith" is used for matching rather than exact match because class under test is written in Scala and for Scala part of the field names are generated by compiler, so not possible to find exact match. Java reflection has getDeclaredField function that accept field name also. 

Once member is marked as accessible then read/write is possible for that field.

Sample call to this API will look something like below

fieldValue("cachedData", sqlSession.sharedState().cacheManager(), LinkedList.class)
Unit test code checking cache can be something like below 

LinkedList cachedData = fieldValue("cachedData", sparkSession().sharedState().cacheManager(), LinkedList.class);
int before = cachedData.size();
loadVehicleTable();
int after = cachedData.size();
Assert.isTrue(after == before + 1);

Reflection is very powerful and comes handy in such scenario but comes with tradeoff of relaxed type safety guarantee by treating method or variable as String but it is still better than not testing at all. 
 
One more thing that i discovered during this exercise is that JVM spends some time in checking field access and it causes some overhead when reflection is used.
Turning off access check will make code fast also.

With this trick now you can start testing some of the private function that you wished were public or left public only for testing.

Friday, 10 October 2014

Factory Without IF-ELSE

Object Oriented Language has very powerful feature of Polymorphism, it is used to remove if/else or switch case in code.

Code without condition is easy to read. There are some places where you have to put them and one of such example is Factory/ServiceProvider class.
I am sure you have seen factory class with IF-ELSEIF which keeps on getting big.

In this blog i will share some techniques that you can be used to remove condition in factory class.

I will use below code snippet as example



Reflection
This is first thing that comes to mind when you want to remove conditions. You get the feeling of framework developer!



This looks very simple but only problem is caller has to remember fully qualified class name and some time it could be issue.

Map
Map can be used to to map actual class instance to some user friendly name

This also looks neat without overhead of reflection.

Enum
This is interesting one

This method is using enum method to remove condition, one of the issue is that you need Enum for each type. You don't want to create tons of them!
I personally like this method.

 Conclusion
If-else or switch case makes code difficult to understand, we should try to avoid them as much as possible. Language construct should be used to avoid some of switch case.

We should try to code without IF-ELSE and that will force us to come up with better solution.

Saturday, 28 June 2014

MethodHandle returns back in java 8

Longtime back i wrote blog to compare performance of reflection/methodhandle etc.
Methodhandle was introduced in JDK7 and its performance was not that good as compared to reflection.

Recap of test result from JDK 7


MethodHandle is right in bottom as a result it was was not of much use in JDK7.
MethodHandle is used in java 8 lambda and i think due to that lot of improvement was done in it.

Lets have look at JDK8 numbers



MethodHandle implementation of JDK8 is back.
Open JDK mailing conversation has some details about type of optimization that is required in method handle. 

Code used for this blog is available @ github

Update -
One of the reader asked for raw numbers, numbers are in Mili Second





Friday, 11 January 2013

Java Reflection Facts


Java has wonderful feature that allow to inspect any object at run time and extract useful information about it for e.g constructor, methods, fields etc.

Reflection provides flexibility at run time to make decision without writing IF/ELSE, SWITH-CASE, it is used extensively in java and there are lot of framework developed based on it for eg ORM, Rule engine etc

We have to trade off performance for the cost of flexibility that reflections give to us specially if you execute any method via reflection, lets try to measure cost and see what can be done to improve it.


Simple Value Object
Take a simple class Order which has 2 property ( orderId,orderType)


public class Order {
private int orderId;
private String orderType;

public int getOrderId() {
return orderId;
}

public void setOrderId(int orderId) {
this.orderId = orderId;
}

public void setOrderType(String orderType) {
this.orderType = orderType;
}
public String getOrderType() {
return orderType;
}
}



Method Invocation


getOrderId function is called 10 Million time in loop and reflection is around 17X times slow for this test
That is very high cost paid for flexibility!

So what can be done, JDK 1.7 added more feature related to reflection. It is suppose to make life easy for developer by moving lot of plumbing code to java API. MethodHandles class  is supposed to do all the magic related to reflection use case, Lets try to measure it for our simple case.



Wow it is very very slow 106X times slow compared reflection, i don't want to compare with with normal method call. MethodHandles gives good abstraction for reflection, but on performance side it is very slow, so i am sure you want to re think before you use it.

What are the other options
What are the options to make it fast
 - Go back to normal method call by writing big IF-ELSEIF-ELSE for each method
 - Use some native call to perform reflection.

First option looks such a naive thing, you don't want to write all that and if your class has lot of function then it become nightmare to maintain it. There are some byte code manipulation API that we can use to generate such class. There are couple of options ASMjavassist for that.

May java developer don't want to use second option because you want to stay away from native code due to portability issue, but it is worth trying it to see what type of performance we get. java has Unsafe class which is used internally by java for many things, i will also try to use this to find alternate ways of reflection.

Below is the chart for call of getOrderType 10 Million times

Wow this is some thing, using compiled class ( via javaassit) & Unsafe we can come close to normal method call. I will remove JDK 7 from graph, so that we have some proper scale in graph.


Now it is better, Unsafe is almost same as Normal method. Compiled is better than reflection, it amount 1.8X times faster than reflection.
There are some options to improve performance of "Compiled" class, the current implementation has below code 

        if("getOrderType".equals(s))
            return (String)((com.atomic.RefTest.Order)obj).getOrderType();
        if("getOrderId".equals(s))
            return Integer.valueOf(((com.atomic.RefTest.Order)obj).getOrderId());

There are if condition for making decision which method to call, if we can remove that we might get some performance improvement, so now it will look like 

((com.atomic.ReflectionTest.Order)obj).getOrderType();

Below is graph with that change - CompiledSingleProp is one with no IF condition 

Performance of CompiledSingleProp is similar to Unsafe and close to Normal function call.
So we can definitely use "Option 1" for reflection without significant performance impact on application.

Performance compare Object vs primitive property
While doing this test i notice performance of primitive property is slow as compared to object property and reason is because we have to create Wrapper class to represent primitive type and it adds overhead.
Below is graph for comparing primitive vs object property
  

Compiled class performs better in case of object and it is slow for primitive type(int/float/long), but Unsafe performance has not effect on type of property, so based on use case proper alternate solution can be used to get best performance.

Conclusion
There are many alternate of reflection available, this post talks about few. Compiled class & Unsafe are the most efficient way to perform property get/set calls. These options should be consider if your application is using reflections heavily. Lot of professional tools uses's compiled property. 

About Sample Code

Code available @ github 
For unsafe i am not generating any code, it can easily done using logic similar to PropertyGenerator 


 Java Reflection Example