Kabir Khan [http://community.jboss.org/people/kabir.khan%40jboss.com] replied 
to the discussion

"JBREFLECT-5 - Implementing generics in JavassistClassInfo"

To view the discussion, visit: http://community.jboss.org/message/539587#539587

--------------------------------------------------------------
After a few false starts I have managed to reproduce the error described in my 
last post, and while doing so found another problem to do with caching. Both of 
these problems are related and have to do with difficulties in determining the 
correct classloader to use for ParamerizedType.

1 - Other problem
> Kabir Khan wrote:
> 
> > alesj wrote:
> > 
> > As all of the stuff in Reflect works this way, why is this here a problem?
> Not really a problem, I just wanted to check if the object equality is 
> required. It seems to work that way normally, so I'll do that for this 
> instead as well.
The problem here is that if I generate some classes in classloader so they 
don't exist in the main classloader. I generate this set of classes twice in 
two different classloaders

public class SomeValue{}
 
public class SomeSignature
{
   public java.util.Set<SomeValue> signature
   {
      return null;
   } 
}


I generate the classes twice, now if I do something along the lines of

public void testClasses()
{
 
   ClassInfo infoA = getSignatureMethodReturnTypeForClass(loaderA); //One of 
the loaders loading the classes
   ClassInfo infoB = getSignatureMethodReturnTypeForClass(loaderB); //Another 
loader loading the classes
 
   //These all pass
   assertEquals(ClassLoader.getSystemClassLoader(), 
infoA.getRawType().getClassLoader());
   assertEquals(ClassLoader.getSystemClassLoader(), 
infoB.getRawType().getClassLoader());
   assertEquals(loaderA, infoA.getActualTypeArguments[0].getClassLoader());
 
   //Fails - loader is loaderA
   assertEquals(loaderB, infoB.getActualTypeArguments[0].getClassLoader());
 
 
 
}
 
 
 
private void getSignatureMethodReturnTypeForClass(ClassLoader loader)
 
{
 
generateClasses(getPoolForLoader(loader));
 
Class clazz = loader.loadClass("SomeSignature");
 
Method m = loader.getMethod("signature");
 
Type t = m.getGenericReturnType();  //instance of 
java.lang.reflect.ParameterizedType
 
return getTypeInfoFactory().getTypeInfo(t);
 
}
 


The reason this fails is that the parameterized classinfo is cached against the 
string representation of the name, i.e. "java.lang.String<SomeValue>". This 
fails with both the introspection and javassist implementations. 


The root of the problem is this in the entry point to both implementations of 
TypeInfoFactory, and that ParameterizedType has no getClassLoader() method, so 
it is currently guessed by defaulting to the one for the raw type. The 
implementations look something like

   public TypeInfo getTypeInfo(Type type)
   {
      if (type == null)
         throw new IllegalArgumentException("Null type");
 
      if (type instanceof ParameterizedType)
         return getParameterizedType((ParameterizedType) type);
      ...
    }
 
 
    public void getParameterizedType(ParameterizedType type)
    {
        //Check cache
        ClassLoader loader = type.getRawType().getClassLoader();  // 1
        TypeInfo cached = checkLoaderCacheForParameterizedType(loader, 
getName(type)); 
        if (cached != null)
           return true;
 
        //Create parameterized type wrapper
        TypeInfo rawType = getTypeInfo(type.getRawType());
        TypeInfo args = new TypeInfo[type.getActualTypeArguments().length];
        for (int i = 0 ; i < args.length ; i++)
        {
           args[i] = getTypeInfo(type.getActualTypeArguments()[i];
        }
        ClassInfo info = createParameterizedClassInfo(rawType, args);
 
        //Cache the lookup
        cacheParameterizedTypeForLoader(loader, info);
        return info;
    }


So what happens is when we try to get the parameterized type for Set<SomeValue> 
with loaderA it gets cached, but against the classloader of Set, which is the 
system classloader. When we try to get it with loaderB, it is found, but from 
the cache for Set's classloader, i.e. the system classloader. 

So maybe caching should be turned off for parameterized types? I have not yet 
checked what the implications of this would be, but it would mean that object 
equality checks if used will not work for parameterized types created this way. 
Or maybe they should be cached against the context classloader instead?

--------------------------------------------------------------

Reply to this message by going to Community
[http://community.jboss.org/message/539587#539587]

Start a new discussion in JBoss Microcontainer Development at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=1&containerType=14&container=2115]

_______________________________________________
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user

Reply via email to