You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@felix.apache.org by Stefan Egli <st...@apache.org> on 2014/07/14 15:42:44 UTC

Unresolved annotation with embedded class after re-install

Hi,

TL;DR:
It looks like uninstalling a bundle that embeds another jar ­ does not
uninstall those embedded classes and reinstalling the bundle afresh and
resolving a class via Class.forName(embeddedClassName, false,
newBundleClassLoader) returns the old, already uninstalled bundle's
Classloader.

The long story:
I'm encountering an odd behavior in sling-remote-testing which I suspect
could be an issue in the underlying felix layer, that's why I'd like to
see if anyone from the felix-user list can help.

Here's a description of what I'm doing:

* I'm installing a test bundle (with my test class annotated with
@org.junit.runner.RunWith) and a bunch of sling-remote-testing bundles (eg
sling.junit.core, sling.junit.remote, sling.testing.tools). I then start
the first incarnation of these remote tests:
     * all works fine
          * now I note down the bundle ID of sling.junit.core as ID=501
          * PS: sling.junit.core embeds junit-4.8.2.jar !
* Without restarting the server, I run the integration tests again, this
again installs all above mentioned bundles and re-runs the junit remote
tests
     * On this second run though, junit cannot find any tests ("No
runnable methods") and fails
          * I again note down the bundle ID of sling.junit.core as ID=512

I traced the problem down to the fact that junit's AnnotatedBuilder cannot
resolve the @RunWith annotation at [0] (getAnnotation() returns null):
    RunWith annotation = testClass.getAnnotation(RunWith.class);
The reason getAnnotation() returns null is because the testClass contains
the @RunWith annotation loaded by the bundle Classloader of bundle 501
(the first installation of sling.junit.core) - whereas the class that runs
above line (ie Junit itself) is loaded with the bundle ClassLoader of
bundle 512: The result is that the HashMap lookup fails since the two
Classes are not equal.

Somewhere deep in JVM's annotation resolution code (ie in
sun.reflect.generics.Reifier / sun.reflect.generics.CoreReflectionFactory)
the following line is executed:
    Class.forName(name /*org.junit.runner.RunWith*/, false,
getDeclsLoader());whereas getDeclsLoader()==bundle Classloader ID 512 (the
new, correct one) - and interesting enough: the resulting Class has
getClassloader()==bundle Classloader ID 501 (the deleted one)

So either the class loading mechanism is correct (in that it can return
the class loaded with the old, 501, classloader) and JVM's annotation
lookup mechanism is broken - or the class loading mechanism is indeed
broken here

Cheers,
Stefan
--
[0] - 
https://github.com/junit-team/junit/blob/r4.11/src/main/java/org/junit/inte
rnal/builders/AnnotatedBuilder.java#L19



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: Unresolved annotation with embedded class after re-install

Posted by Stefan Egli <st...@apache.org>.
Interesting. That could well explain the problem. The thing is, that this
time, it's JVM code which does Class.forName() ..

An additional detail to my original post: The problem occurred when
installing the same bundle+version on top of an existing one (and that one
had an embedded jar file). So I'd rephrase my claim with this condition.

Also, meanwhile, I have worked around the issue by not re-installing a
bundle if it already exists..

Cheers,
Stefan

On 7/14/14 10:38 PM, "Carsten Ziegeler" <cz...@apache.org> wrote:

>A good read on Class.forName:
>
>http://blog.meschberger.ch/2010/12/classforname-probably-not.html
>
>Regards
>Carsten
>
>
>2014-07-14 6:42 GMT-07:00 Stefan Egli <st...@apache.org>:
>
>> Hi,
>>
>> TL;DR:
>> It looks like uninstalling a bundle that embeds another jar ­ does not
>> uninstall those embedded classes and reinstalling the bundle afresh and
>> resolving a class via Class.forName(embeddedClassName, false,
>> newBundleClassLoader) returns the old, already uninstalled bundle's
>> Classloader.
>>
>> The long story:
>> I'm encountering an odd behavior in sling-remote-testing which I suspect
>> could be an issue in the underlying felix layer, that's why I'd like to
>> see if anyone from the felix-user list can help.
>>
>> Here's a description of what I'm doing:
>>
>> * I'm installing a test bundle (with my test class annotated with
>> @org.junit.runner.RunWith) and a bunch of sling-remote-testing bundles
>>(eg
>> sling.junit.core, sling.junit.remote, sling.testing.tools). I then start
>> the first incarnation of these remote tests:
>>      * all works fine
>>           * now I note down the bundle ID of sling.junit.core as ID=501
>>           * PS: sling.junit.core embeds junit-4.8.2.jar !
>> * Without restarting the server, I run the integration tests again, this
>> again installs all above mentioned bundles and re-runs the junit remote
>> tests
>>      * On this second run though, junit cannot find any tests ("No
>> runnable methods") and fails
>>           * I again note down the bundle ID of sling.junit.core as
>>ID=512
>>
>> I traced the problem down to the fact that junit's AnnotatedBuilder
>>cannot
>> resolve the @RunWith annotation at [0] (getAnnotation() returns null):
>>     RunWith annotation = testClass.getAnnotation(RunWith.class);
>> The reason getAnnotation() returns null is because the testClass
>>contains
>> the @RunWith annotation loaded by the bundle Classloader of bundle 501
>> (the first installation of sling.junit.core) - whereas the class that
>>runs
>> above line (ie Junit itself) is loaded with the bundle ClassLoader of
>> bundle 512: The result is that the HashMap lookup fails since the two
>> Classes are not equal.
>>
>> Somewhere deep in JVM's annotation resolution code (ie in
>> sun.reflect.generics.Reifier /
>>sun.reflect.generics.CoreReflectionFactory)
>> the following line is executed:
>>     Class.forName(name /*org.junit.runner.RunWith*/, false,
>> getDeclsLoader());whereas getDeclsLoader()==bundle Classloader ID 512
>>(the
>> new, correct one) - and interesting enough: the resulting Class has
>> getClassloader()==bundle Classloader ID 501 (the deleted one)
>>
>> So either the class loading mechanism is correct (in that it can return
>> the class loaded with the old, 501, classloader) and JVM's annotation
>> lookup mechanism is broken - or the class loading mechanism is indeed
>> broken here
>>
>> Cheers,
>> Stefan
>> --
>> [0] -
>> 
>>https://github.com/junit-team/junit/blob/r4.11/src/main/java/org/junit/in
>>te
>> rnal/builders/AnnotatedBuilder.java#L19
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> For additional commands, e-mail: users-help@felix.apache.org
>>
>>
>
>
>-- 
>Carsten Ziegeler
>Adobe Research Switzerland
>cziegeler@apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: Unresolved annotation with embedded class after re-install

Posted by Carsten Ziegeler <cz...@apache.org>.
A good read on Class.forName:

http://blog.meschberger.ch/2010/12/classforname-probably-not.html

Regards
Carsten


2014-07-14 6:42 GMT-07:00 Stefan Egli <st...@apache.org>:

> Hi,
>
> TL;DR:
> It looks like uninstalling a bundle that embeds another jar ­ does not
> uninstall those embedded classes and reinstalling the bundle afresh and
> resolving a class via Class.forName(embeddedClassName, false,
> newBundleClassLoader) returns the old, already uninstalled bundle's
> Classloader.
>
> The long story:
> I'm encountering an odd behavior in sling-remote-testing which I suspect
> could be an issue in the underlying felix layer, that's why I'd like to
> see if anyone from the felix-user list can help.
>
> Here's a description of what I'm doing:
>
> * I'm installing a test bundle (with my test class annotated with
> @org.junit.runner.RunWith) and a bunch of sling-remote-testing bundles (eg
> sling.junit.core, sling.junit.remote, sling.testing.tools). I then start
> the first incarnation of these remote tests:
>      * all works fine
>           * now I note down the bundle ID of sling.junit.core as ID=501
>           * PS: sling.junit.core embeds junit-4.8.2.jar !
> * Without restarting the server, I run the integration tests again, this
> again installs all above mentioned bundles and re-runs the junit remote
> tests
>      * On this second run though, junit cannot find any tests ("No
> runnable methods") and fails
>           * I again note down the bundle ID of sling.junit.core as ID=512
>
> I traced the problem down to the fact that junit's AnnotatedBuilder cannot
> resolve the @RunWith annotation at [0] (getAnnotation() returns null):
>     RunWith annotation = testClass.getAnnotation(RunWith.class);
> The reason getAnnotation() returns null is because the testClass contains
> the @RunWith annotation loaded by the bundle Classloader of bundle 501
> (the first installation of sling.junit.core) - whereas the class that runs
> above line (ie Junit itself) is loaded with the bundle ClassLoader of
> bundle 512: The result is that the HashMap lookup fails since the two
> Classes are not equal.
>
> Somewhere deep in JVM's annotation resolution code (ie in
> sun.reflect.generics.Reifier / sun.reflect.generics.CoreReflectionFactory)
> the following line is executed:
>     Class.forName(name /*org.junit.runner.RunWith*/, false,
> getDeclsLoader());whereas getDeclsLoader()==bundle Classloader ID 512 (the
> new, correct one) - and interesting enough: the resulting Class has
> getClassloader()==bundle Classloader ID 501 (the deleted one)
>
> So either the class loading mechanism is correct (in that it can return
> the class loaded with the old, 501, classloader) and JVM's annotation
> lookup mechanism is broken - or the class loading mechanism is indeed
> broken here
>
> Cheers,
> Stefan
> --
> [0] -
> https://github.com/junit-team/junit/blob/r4.11/src/main/java/org/junit/inte
> rnal/builders/AnnotatedBuilder.java#L19
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>
>


-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org