<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<body link="#355491" alink="#4262a1" vlink="#355491" style="background: #e2e2e2; margin: 0; padding: 20px;">

<div>
        <table cellpadding="0" bgcolor="#FFFFFF" border="0" cellspacing="0" style="border: 1px solid #dadada; margin-bottom: 30px; width: 100%; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
                <tbody>
                        <tr>

                                <td>

                                        <table border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" style="border: solid 2px #ccc; background: #dadada; width: 100%; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
                                                <tbody>
                                                        <tr>
                                                                <td bgcolor="#000000" valign="middle" height="58px" style="border-bottom: 1px solid #ccc; padding: 20px; -moz-border-radius-topleft: 3px; -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 5px; -webkit-border-top-left-radius: 5px;">
                                                                        <h1 style="color: #333333; font: bold 22px Arial, Helvetica, sans-serif; margin: 0; display: block !important;">
                                                                        <!-- To have a header image/logo replace the name below with your img tag -->
                                                                        <!-- Email clients will render the images when the message is read so any image -->
                                                                        <!-- must be made available on a public server, so that all recipients can load the image. -->
                                                                        <a href="http://community.jboss.org/index.jspa" style="text-decoration: none; color: #E1E1E1">Community</a></h1>
                                                                </td>

                                                        </tr>
                                                        <tr>
                                                                <td bgcolor="#FFFFFF" style="font: normal 12px Arial, Helvetica, sans-serif; color:#333333; padding: 20px;  -moz-border-radius-bottomleft: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 5px; -webkit-border-bottom-left-radius: 5px;"><h3 style="margin: 10px 0 5px; font-size: 17px; font-weight: normal;">
    JBREFLECT-5 - Implementing generics in JavassistClassInfo
</h3>
<span style="margin-bottom: 10px;">
    reply from <a href="http://community.jboss.org/people/kabir.khan%40jboss.com">Kabir Khan</a> in <i>JBoss Microcontainer Development</i> - <a href="http://community.jboss.org/message/539587#539587">View the full discussion</a>
</span>
<hr style="margin: 20px 0; border: none; background-color: #dadada; height: 1px;">

<div class="jive-rendered-content"><p>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.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>1 - Other problem</p><blockquote class="jive-quote"><p>Kabir Khan wrote:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><blockquote class="jive-quote"><p>alesj wrote:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>As all of the stuff in Reflect works this way, why is this here a problem?</p></blockquote><p>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 <span>instead</span> as well.</p></blockquote><p>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</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><pre class="jive-pre"><code class="jive-code jive-java"><font color="navy"><b>public</b></font> <font color="navy"><b>class</b></font> SomeValue<font color="navy">{</font><font color="navy">}</font>
&#160;
<font color="navy"><b>public</b></font> <font color="navy"><b>class</b></font> SomeSignature
<font color="navy">{</font>
&#160;&#160; <font color="navy"><b>public</b></font> java.util.Set&lt;SomeValue&gt; signature
&#160;&#160; <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>return</b></font> <font color="navy"><b>null</b></font>;
&#160;&#160; <font color="navy">}</font> 
<font color="navy">}</font>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>I generate the classes twice, now if I do something along the lines of</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><pre class="jive-pre"><code class="jive-code jive-java"><font color="navy"><b>public</b></font> <font color="navy"><b>void</b></font> testClasses()
<font color="navy">{</font>
&#160;
&#160;&#160; ClassInfo infoA = getSignatureMethodReturnTypeForClass(loaderA); <font color="darkgreen">//One of the loaders loading the classes</font>
&#160;&#160; ClassInfo infoB = getSignatureMethodReturnTypeForClass(loaderB); <font color="darkgreen">//Another loader loading the classes</font>
&#160;
&#160;&#160; <font color="darkgreen">//These all pass</font>
&#160;&#160; assertEquals(ClassLoader.getSystemClassLoader(), infoA.getRawType().getClassLoader());
&#160;&#160; assertEquals(ClassLoader.getSystemClassLoader(), infoB.getRawType().getClassLoader());
&#160;&#160; assertEquals(loaderA, infoA.getActualTypeArguments[0].getClassLoader());
&#160;
&#160;&#160; <font color="darkgreen">//Fails - loader is loaderA</font>
&#160;&#160; assertEquals(loaderB, infoB.getActualTypeArguments[0].getClassLoader());
 
&#160;
&#160;
<font color="navy">}</font>
&#160;
&#160;
&#160;
<font color="navy"><b>private</b></font> <font color="navy"><b>void</b></font> getSignatureMethodReturnTypeForClass(ClassLoader loader)
&#160;
<font color="navy">{</font>
&#160;
generateClasses(getPoolForLoader(loader));
&#160;
Class clazz = loader.loadClass(<font color="red">"SomeSignature"</font>);
&#160;
Method m = loader.getMethod(<font color="red">"signature"</font>);
&#160;
Type t = m.getGenericReturnType();&#160; <font color="darkgreen">//instance of java.lang.reflect.ParameterizedType</font>
&#160;
<font color="navy"><b>return</b></font> getTypeInfoFactory().getTypeInfo(t);
&#160;
<font color="navy">}</font>
&#160;
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>The reason this fails is that the parameterized classinfo is cached against the string representation of the name, i.e. "java.lang.String&lt;SomeValue&gt;". This fails with both the introspection and javassist implementations. </p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>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</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><pre class="jive-pre"><code class="jive-code jive-java">&#160;&#160; <font color="navy"><b>public</b></font> TypeInfo getTypeInfo(Type type)
&#160;&#160; <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (type == <font color="navy"><b>null</b></font>)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>throw</b></font> <font color="navy"><b>new</b></font> IllegalArgumentException(<font color="red">"Null type"</font>);
&#160;
&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (type <font color="navy"><b>instanceof</b></font> ParameterizedType)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>return</b></font> getParameterizedType((ParameterizedType) type);
&#160;&#160;&#160;&#160;&#160; ...
&#160;&#160;&#160; <font color="navy">}</font>
 
&#160;
&#160;&#160;&#160; <font color="navy"><b>public</b></font> <font color="navy"><b>void</b></font> getParameterizedType(ParameterizedType type)
&#160;&#160;&#160; <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="darkgreen">//Check cache</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; ClassLoader loader = type.getRawType().getClassLoader();&#160; <font color="darkgreen">// 1</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; TypeInfo cached = checkLoaderCacheForParameterizedType(loader, getName(type)); 
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (cached != <font color="navy"><b>null</b></font>)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>return</b></font> <font color="navy"><b>true</b></font>;
&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="darkgreen">//Create parameterized type wrapper</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; TypeInfo rawType = getTypeInfo(type.getRawType());
&#160;&#160;&#160;&#160;&#160;&#160;&#160; TypeInfo args = <font color="navy"><b>new</b></font> TypeInfo[type.getActualTypeArguments().length];
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>for</b></font> (<font color="navy"><b>int</b></font> i = 0 ; i &lt; args.length ; i++)
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; args[i] = getTypeInfo(type.getActualTypeArguments()[i];
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; ClassInfo info = createParameterizedClassInfo(rawType, args);
&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="darkgreen">//Cache the lookup</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; cacheParameterizedTypeForLoader(loader, info);
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>return</b></font> info;
&#160;&#160;&#160; <font color="navy">}</font>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>So what happens is when we try to get the parameterized type for Set&lt;SomeValue&gt; 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. </p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>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?</p></div>

<div style="background-color: #f4f4f4; padding: 10px; margin-top: 20px;">
    <p style="margin: 0;">Reply to this message by <a href="http://community.jboss.org/message/539587#539587">going to Community</a></p>
        <p style="margin: 0;">Start a new discussion in JBoss Microcontainer Development at <a href="http://community.jboss.org/choose-container!input.jspa?contentType=1&containerType=14&container=2115">Community</a></p>
</div></td>
                        </tr>
                    </tbody>
                </table>


                </td>
            </tr>
        </tbody>
    </table>

</div>

</body>
</html>