Community

JBoss Reflect Performance Javassist vs Introspection

reply from Kabir Khan in JBoss Microcontainer Development - View the full discussion

What we generate is effectively something along the lines of

 

public class JavassistMethod1 implements JavassistMethod
{
   public Object invoke(Object target, Object[] args) throws Throwable
   {
      if (target == null)
         throw new IllegalArgumentException("Null target");
      if (target instanceof SomeClass == false)
         throw new IllegalArgumentException("Wrong target");
      
      if (args == null || args.length != 10) 
         throw new IllegalArgumentException("Wrong number of parameters");
      
      if (args[0] == null) 
         throw new IllegalArgumentException("Parameter 1 cannot be null for SomeClass.someMethod(long, String)");
      if (args[0] != null && args[0] instanceof Long == false) 
         throw new IllegalArgumentException("Parameter 1 is not an instance of Long for SomeClass.someMethod(long, String)");
      
      if (args[1] != null && args[1] instanceof String == false) 
         throw new IllegalArgumentException("Parameter 2 is not an instance of String for SomeClass.someMethod(long, String)");
      
      return ((SomeClass)target).someMethod(((Long)args[0]).longValue(), (String)args[1]);      
   }
}

 

Disabling the parameter checking so we end up with this instead reduces the time spent in C from about 4.8s to 3.8s

 

public class JavassistMethod1 implements JavassistMethod
{
   public Object invoke(Object target, Object[] args) throws Throwable
   {
      return ((SomeClass)target).someMethod(((Long)args[0]).longValue(), (String)args[1]);      
 
   }
} 
 

 

Profiling this, for each JavassistMethod implementation the time taken is roughly

 

50% generating the bytecode for the method

30% Converting the bytecode to a byte array and creating the class

13% creating the constructor

6% setting the interfaces

 

Maybe a better approach would be

1) to do the parameter checking in Javassist[Constructor/Method/Field]Info itself

2) to generate less classes? Something like:

 

public class SomeBeanAccessor implements JavassistBeanAccessor
{
    public Object newInstance(int index, Object[] args) throws Throwable
    {
       if (index == 0)
          return new SomeClass((String)args[0]);
       else if (index == 1)
          return new SomeClass((String)args[1]);
 
       return null;
    }
 
    public Object invoke(long hash, Object target, Object[] args) throws Throwable
    {
        if (hash == 121267912)
      return ((SomeClass)target).someMethod(((Long)args[0]).longValue(), (String)args[1]);
    if (hash == 128172981)
 
      return ((SomeClass)target).otherMethod(((Long)args[0]).longValue(), (String)args[1], (String)args[2]);
 
   }
 
 
 
   public Object get(String name, Object target) throws Throwable
 
   {
 
      if (name.equals("intField")
 
          return Integer.valueOf(((SomeClass)target).intField);
 
      if (name.equals("stringField")
 
          return ((SomeClass)target).stringField;
 
   }
 
 
 
   public void set(String name, Object target, Object value) throws Throwable
 
   {
 
      if (name.equals("intField")
 
          ((SomeClass)target).intField = ((Integer)value).intValue();
 
          return;
 
      if (name.equals("stringField")
 
          ((SomeClass)target).stringField = (String)value;
 
   }
 
}
 

 

First call by Javassist[Constructor/Method/Field]Info to access the member would result in this being created for ALL members, and cached in JavassistTypeInfo.

Reply to this message by going to Community

Start a new discussion in JBoss Microcontainer Development at Community