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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to